Recipe: Monitor EU public tenders
The task
A business-development or public-affairs team wants a recurring (daily or weekly) check for new government tenders across the EU in their sector — the “tell me when something new opens” version of tender search, run on a schedule.
Tools used: per-country tender packs — france_search_tenders, germany_search_tenders,
nl_tender_search, es_tender_search, dk_tender_search — plus oc_tender_search for
Italy and Croatia. Not eu_search_tenders — see below.
Copy-paste prompt
Set up a recurring check for new public-procurement tenders in "<sector/keyword>" across
the EU member states Pipeworx actually covers (France, Germany, Netherlands, Spain,
Denmark, Italy, Croatia). For each covered country, run its national tender search tool
with the keyword and today's date window, and list new notices with title, buyer,
deadline, and URL. Explicitly tell me which EU member states are NOT covered so I know
this isn't a full-EU sweep.
What a good answer looks like
france_search_tenders({ query: "informatique", limit: 3 })
returns (live call, 2026-08-10 — trimmed to 1 of 3):
{
"total_count": 29445,
"notices": [
{
"id": "26-79055",
"object": "Accord-cadre relatif au développement et au maintien en condition opérationnelle (MCO) des outils informatiques composant le Domaine Civil",
"buyer": "Ministère de la justice",
"publication_date": "2026-08-09",
"contract_type": ["Services"],
"status": "INITIAL",
"url": "https://www.boamp.fr/pages/avis/?q=idweb:26-79055"
}
]
}
paired with:
germany_search_tenders({ query: "Software", date_from: "2026-08-03", date_to: "2026-08-10", limit: 3 })
// → 3 real German federal-procurement notices, newest first, published 2026-08-09/10
A trustworthy recurring-monitor answer:
- names which specific national portals were actually queried this run (BOAMP for France, oeffentlichevergabe.de for Germany, etc.) — not “the EU tender database”
- states the date window actually fetched, not just the window requested — see the Germany caveat below, where these can silently differ
- lists, by name, the EU member states not covered, so a reader can’t mistake a 7-country sweep for a 27-country one
The plausible-sounding failure: asking for “EU tenders” and getting eu_search_tenders
results that look like exactly what was asked for, but aren’t. Live call, no query
text, status “open”:
eu_search_tenders({ status: "open", limit: 5 })
returns real-looking procurement notices — reference numbers, EUR budgets, deadlines, portal URLs:
{
"total_results": 21,
"results": [
{ "reference": "EuropeAid/186661/DD/ACT/JM", "country": "JM",
"title": "Human Rights and Democracy Support in Jamaica 2026 and 2027",
"budget": "600000", "currency": "EUR" },
{ "reference": "EuropeAid/186614/DD/ACT/Multi", "country": "Multi",
"title": "Papua New Guinea (PNG) — Civic Participation and Women's Political and Decision-making Participation",
"budget": "1381333", "currency": "EUR" }
],
"source": "EU Funding & Tenders Portal (SEDIA), external-action tenders and calls"
}
Every one of the 21 open results is an EU external-action development-aid contract to a
non-EU country (Jamaica, Papua New Guinea, South Africa, Palestine, North Macedonia were
the top live results). eu_search_tenders searches the EU Funding & Tenders Portal —
European Commission external-action and EuropeAid grants — not member-state public
procurement (the TED / Tenders Electronic Daily universe). A caller who asks “monitor EU
public tenders,” gets this tool by name-match, and doesn’t read the source field
carefully will build a recurring monitor on the wrong dataset and never notice, because
nothing about the response looks like an error. Filed as fleet #216 (naming/discoverability
issue); documented here so it doesn’t cost you the same way in the meantime.
Step-by-step tool calls
1. Query each covered country separately
There is no single call that sweeps the whole EU. Run one call per covered country:
france_search_tenders({ query: "<keyword>", limit: 20 }) // BOAMP
germany_search_tenders({ query: "<keyword>", date_from: "<today-7d>", date_to: "<today>", limit: 20 }) // oeffentlichevergabe.de
nl_tender_search({ query: "<keyword>", limit: 20 }) // TenderNed
es_tender_search({ query: "<keyword>", limit: 20 }) // PLACSP (use Spanish keywords)
dk_tender_search({ query: "<keyword>", limit: 20 }) // udbud.dk (use Danish keywords)
oc_tender_search({ query: "<keyword>", country: "Italy", days: 7, limit: 20 })
oc_tender_search({ query: "<keyword>", country: "Croatia", days: 7, limit: 20 })
Spain and Denmark rank on keyword recall in their own language — an English keyword will under-match. Translate the term before querying, or accept lower recall.
2. For Germany specifically, mind the per-call fetch cap
germany_search_tenders({ query: "Software", date_from: "2026-07-01", date_to: "2026-08-10", limit: 3 })
// → days_fetched: ["2026-08-10"] (only ONE day actually fetched, even though a
// 40-day window was requested)
The tool fetches at most 7 days per call (newest first), and stops early once it has
collected limit matching results — so a low limit on a day with plenty of hits can
mean only the most recent day was ever queried, silently. For a genuine recurring daily
monitor this is fine (you only need the last day or two each run); for a one-off backfill
over a longer window, raise limit well above what you expect per day, or narrow
date_from/date_to to walk the range in 7-day chunks.
3. Recurring cadence
Run the covered-country calls on a schedule (daily is safe for all of them; France and
Germany publish daily). Track which notice id/ocid values you’ve already surfaced
between runs — none of these tools take a “since last check” cursor, so dedup is on you.
4. State the gap every time
Of the EU’s 27 member states, Pipeworx has real national tender-portal coverage for France, Germany, Netherlands, Spain, Denmark, Italy, and Croatia — 7 of 27. The other 20 (Poland, Belgium, Sweden, Austria, Portugal, Ireland, Greece, Czechia, Hungary, Romania, Bulgaria, Slovakia, Slovenia, Lithuania, Latvia, Estonia, Finland, Luxembourg, Malta, Cyprus) have no dedicated tool in the catalog today. A monitor built only from the covered 7 is legitimate and useful — as long as it’s labeled as 7 countries, not “the EU.”
Caveats
eu_search_tendersis EU external-action/EuropeAid aid contracts, not member-state procurement. Repeated from above because it’s the single most important thing to get right in this recipe — don’t use it for a “monitor EU public tenders” ask.- No TED-wide tool exists in the catalog. TED (Tenders Electronic Daily) is the EU’s
actual above-threshold procurement-wide notice system; Pipeworx doesn’t mirror it
directly, only 7 national portals plus a UK post-Brexit equivalent
(
find_a_tender_recent— UK is not in the EU, include it only if the ask covers the UK too). - Per-country result shapes differ. France returns
object(nottitle), Germany returnsocid+OCDS fields, Netherlands returns Dutch notice-type codes, Spain and Denmark are native-language. Don’t assume a uniform schema across countries when merging results into one list. - Language matters for recall, not just for reading results — Spanish, Dutch, Danish, and German portals all rank best on native-language keywords per their own tool descriptions.
- “Open” status can lag the deadline slightly.
eu_search_tendersitself notes a handful of tenders keep status Open past their nominal deadline; the per-country tools don’t all filter this the same way — checkresponse_deadline/deadlinefields rather than trusting a status word alone when the ask is “still open to bid.”