EU Tender Monitor - TED Alerts
Pricing
from $1.60 / 1,000 baseline tenders
EU Tender Monitor - TED Alerts
Get alerted the moment a new EU public tender matching your business is published on TED. Filter by CPV codes, keywords in any EU language, countries and NUTS regions; alerts only on never-seen tenders via the official TED API. Clean output, no buyer contact persons.
Pricing
from $1.60 / 1,000 baseline tenders
Rating
0.0
(0)
Developer
Lowland Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
0
Monthly active users
2 days ago
Last modified
Categories
Share
EU Tender Monitor — TED Alerts
Watches TED (Tenders Electronic Daily, the EU's official procurement journal — every above-threshold public tender in the Union) for notices matching your buyer profile: CPV codes, keywords in any EU language, countries, NUTS regions, value floor. It alerts the moment a matching tender is published, and it remembers what it has already told you — so an alert always means something changed, never a re-scrape of yesterday's list.
It reads the official TED Search API — the access route the EU itself provides for reuse — and the output is GDPR-clean by construction: buyer organizations, CPV codes, deadlines and values, but no contact persons, no emails, no phone numbers. Safe to store, share with your bid team, or import into a CRM.
Quick start (30 seconds, no account or API keys needed)
- Run the actor with the prefilled input (IT-services tenders, EU-wide, last 3 days) — it finishes in a few seconds and shows a baseline.
- Replace the demo profile with your own: your CPV codes, your keywords, your countries or NUTS regions.
- Add a daily schedule (Actor page → Schedule). From then on, runs are quiet until a tender you care about is actually published.
Who uses this
- A software agency in Antwerp monitors
cpvCodes: ["72000000"],countries: ["BE", "NL"]on a daily schedule. When a hospital publishes a systems-integration tender, the alert lands with thedeadlineand theted.europa.eulink the same day — not when a sales rep stumbles on it in week three of a five-week window. - A bid manager at a construction group watches
nutsCodes: ["BE2"](Flanders) pluscpvCodes: ["45000000"]withminValueEur: 1000000— only the region she can actually serve, only projects worth mobilizing for. - A consultancy tracking its competitors monitors
noticeTypes: ["award"]on its CPV family:winnerNamesandtotalValueEurshow who wins what, at what price, across every EU member state. - A market-entry analyst runs
keywords: ["laboratorium", "laboratory"]EU-wide for a quarter of demand data — TED translates every title into all 24 EU languages, so keywords match tenders from Portugal to Finland. - A grants-and-tenders desk pairs this with its US sibling (US RFP Monitor) for one transatlantic pipeline with identical alert semantics.
What you get
One JSON item per event: a baseline snapshot per tender on the first run, then only transitions — new matching tenders, and (opt-in) corrigenda or change notices to tenders you have already seen. A new-tender alert looks like:
{"publicationNumber": "495369-2026","title": "Poland – Software package and information systems – Dostawa i wdrożenie systemu informatycznego","buyerName": "Szpital Wojewódzki w Katowicach","buyerCountry": "POL","cpvCodes": ["48000000", "72263000"],"nutsCodes": ["PL22A"],"noticeCategory": "contract-notice","sourceNoticeType": "cn-standard","description": "Przedmiotem zamówienia jest dostawa i wdrożenie systemu informatycznego wraz z usługami utrzymania.","sourceLanguage": "pol","publicationDate": "2026-07-17","deadline": "2026-08-20","estimatedValueEur": 1030063,"url": "https://ted.europa.eu/en/notice/-/detail/495369-2026","isBaseline": false,"isUpdate": false}
Field honesty notes:
titleis TED's official translation (all 24 EU languages exist; you get English). Its pattern is "Country – CPV label – buyer's own words", and the buyer's own words stay in the source language.descriptionis source-language only — TED does not translate descriptions.sourceLanguagetells you which.estimatedValueEur/totalValueEurappear only when the buyer published a value — most notices carry none, and absence does not mean small.deadlineis the earliest lot deadline on the notice; always verify on the linked notice before planning a bid.- Award notices carry
winnerNamesandwinnerCountries— organization names as the EU officially publishes them, no contact data.
How much does EU tender monitoring cost?
Pay per outcome — checking costs nothing; you pay when the monitor tells you something new:
- New matching tender (the alert): $0.02 — also for change alerts.
- Baseline item (first run only): $0.002.
- Actor start: $0.005. Everything included - there are no separate platform-usage charges, and higher Apify plans get automatic unit-price discounts.
Cost feel: a focused profile (one CPV family, two countries) sees a handful of new tenders per working day → roughly $2–8/month for complete coverage of your niche, with the one-time baseline (say 100 items) costing about $0.20. A run with zero new matches costs $0.005 all-in. Dedicated EU tender-alert services charge €30–200/month for the same coverage.
Why an alert costs more than a scraped row
The store's headline ("from $2.00 / 1,000 baseline results") is what a trial costs: a 100-item baseline ≈ $0.20. Apify displays every event per 1,000, so in the pricing table the alert event reads "$20.00 / 1,000" next to raw scrapers at $1–3 per 1,000 rows — but that comparison is between different things:
- A raw TED scraper sells rows: to monitor with rows you re-download your whole query every day (~3,500 EU notices/working day) and diff them yourself.
- This monitor sells the transition: it remembers state in your account and charges $0.02 exactly when a tender you have not seen matches your profile. Nobody buys 1,000 alerts a month.
Not technical? Let your AI assistant set it up
Paste this prompt together with a description of what you sell and where:
Set up the Apify actor lowlanddata/eu-tender-monitor to watch EU public tendersfor me. Build the input JSON from my business description:- cpvCodes: the EU CPV classification codes for my products/services (8 digits,e.g. 72000000 for IT services; a prefix like "72" also works)- keywords: 3-8 words in any EU language a tender title would contain (they matchTED's official titles in all 24 languages)- countries: ISO codes of countries I can serve (e.g. ["BE", "NL"]), ornutsCodes for regions (e.g. ["BE2"] for Flanders)- noticeTypes: ["contract-notice"] to bid, add "award" to track winners- minValueEur only if I gave a minimum deal sizeLeave alertOn, emitBaseline and maxItems at their defaults. Run it once and showme the baseline as a table (title, buyer, country, deadline, value, url). Thencreate a daily schedule for it and set up a notification so I get an email whena run produces items.
Coverage — measured, not promised
- Source: the official TED Search API, keyless. TED carries every above-EU-threshold tender from all member states plus EEA and enlargement countries — ~3,500–4,100 notices per working day (measured July 2026), zero on weekends (the OJ S publishes working days only).
- Below-threshold national tenders are out of scope by design — they live on national portals (BOAMP, TenderNed, PLACSP, …), not TED. This actor is the EU layer; it does not pretend otherwise.
- Keyword matching: titles in all 24 EU languages (server-side, official TED
index). Descriptions only in their source language, and only with
alsoMatchDescriptions: true. CPV codes are the reliable, language-free filter — prefer them. - A profile broader than ~10,000 notices per run is truncated honestly (the run status says so and suggests narrowing) — precision over silent gaps.
How the monitor thinks
- First run = baseline. It fetches your profile's matches from the last
lookbackDays(default 7), pushes them flaggedisBaseline: trueat the low baseline price, and memorizes them.emitBaseline: falseseeds silently instead. - After that, only transitions. Each run queries from the previous run (one
day of overlap; the memory absorbs duplicates) and pushes only tenders it has
never alerted. Corrigenda and change notices to seen tenders alert as
isUpdate: truewhenalertOn: "new-and-updated"; withalertOn: "new"they stay silent but are remembered, so switching later never replays history. - Editing the profile starts a fresh baseline — matching-relevant inputs are
the profile's identity, so a changed profile can never flood you with alerts
computed against another profile's memory.
maxItems,emitBaselineand schedule changes do not restart anything. - Memory lives in a named key-value store (
stateStoreName, defaultted-monitor-state) in your account. Run several profiles on separate schedules against the same store — they never interfere.resetState: truewipes the current profile's memory. - Re-running after a crash or overlap re-alerts at most the last few unsaved items — state is checkpointed during the run.
Input reference
| Field | Type | Default | Notes |
|---|---|---|---|
keywords | array | [] | Any EU language; matched against official titles in all 24 languages. OR within the list. |
cpvCodes | array | ["72000000"]* | Hierarchical: 72000000 or the prefix 72 match all IT-services codes. |
countries | array | [] | Buyer country, 2- or 3-letter ISO (BE or BEL). |
nutsCodes | array | [] | Place of performance, prefix match (BE2 = Flanders). |
noticeTypes | array | ["contract-notice"] | Also: prior-information, award. |
alsoMatchDescriptions | boolean | false | Descriptions are source-language only — see coverage notes. |
minValueEur | integer | — | Tenders without a published value always pass. |
lookbackDays | integer | 7 | Baseline reach on the first run (max 30). |
alertOn | string | "new" | "new-and-updated" adds corrigendum/change alerts. |
emitBaseline | boolean | true | false = silent seeding. |
resetState | boolean | false | One-shot: wipe this profile's memory. |
maxItems | integer | 500 | Overflow alerts on the next run, never lost. |
stateStoreName | string | "ted-monitor-state" | Only change to fully isolate monitor instances. |
* At least one of keywords, cpvCodes, countries, nutsCodes is required —
an unfiltered profile would be all of TED.
Scheduling and API use
Run it daily (TED publishes working days only — weekend runs simply find nothing and cost $0.005). Pair the schedule with a Monitoring alert on "dataset items
0" to get an email exactly when a tender matched.
curl -X POST \"https://api.apify.com/v2/acts/lowlanddata~eu-tender-monitor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"cpvCodes": ["72000000"], "countries": ["BE"], "lookbackDays": 7}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('lowlanddata/eu-tender-monitor').call({cpvCodes: ['72000000'],countries: ['BE', 'NL'],});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items); // only new tenders since the last run
from apify_client import ApifyClientclient = ApifyClient(os.environ["APIFY_TOKEN"])run = client.actor("lowlanddata/eu-tender-monitor").call(run_input={"cpvCodes": ["72000000"],"countries": ["BE", "NL"],})items = client.dataset(run["defaultDatasetId"]).list_items().items
Typical daily runs finish in well under a minute, comfortably inside the 300s sync-call wall; a 30-day EU-wide baseline on a broad CPV family is the one case that can take a few minutes — run it async once.
Use it with AI agents (MCP)
Claude, Cursor and other MCP-capable agents can run this monitor as a tool through Apify's hosted MCP server: the agent builds the profile from a plain-language brief, runs it, and reads the alerts back — no glue code.
Claude Code:
$claude mcp add apify --transport http "https://mcp.apify.com?actors=lowlanddata/eu-tender-monitor"
Cursor or Claude Desktop (add a custom connector / MCP server with this URL):
https://mcp.apify.com?actors=lowlanddata/eu-tender-monitor
Sign in with your Apify account when prompted — runs are billed to it. Setup details per client: Apify MCP docs, or start from this actor's own MCP page: apify.com/lowlanddata/eu-tender-monitor/api/mcp.
Prompts that work once connected:
- "Watch EU tenders for cloud migration services in Belgium and the Netherlands and show me today's matches."
- "What IT tenders over €500k were published in Flanders this week?"
- "Who won public software tenders in Spain this month, and at what value?"
Is it legal to monitor EU tenders?
Yes — unambiguously. TED is the EU's official publication channel and its notices "can be freely reused, for commercial or non-commercial purposes" under the European Commission's reuse decision (2011/833/EU); this actor reads the official TED Search API that exists exactly for this. No login walls, no anti-bot bypass — if TED is unreachable, the run reports it rather than fighting it. And the output is safe by construction: no personal data is requested from the API in the first place (see the compliance section below).
Data source: Tenders Electronic Daily (TED), © European Union, ted.europa.eu — reused under Commission Decision 2011/833/EU.
Compliance: safe to store, safe to CRM-import
TED notices do contain personal data — buyer contact persons with direct emails
and phone numbers, and beneficial-ownership names. This actor's guarantee is
structural, not a filter: the TED API only returns fields that are explicitly
requested, and the request whitelist simply never includes the person, contact,
email, phone or beneficial-owner field families — the data never even crosses the
wire, and an automated test proves that a response carrying such fields cannot
reach the output. What remains is organization-level: buyer names, winner
organization names, codes, dates, values. One honest limit: description and
title contain text the buyer wrote — on rare occasions a buyer writes a person's
name into free text. We cannot rewrite official notices; everything structured is
guaranteed clean.
FAQ
Why did my second run return nothing? Because nothing new matched — that is the product working. The first run is the baseline; afterwards you only pay for tenders you have not seen. Check the run status line: it says how many notices were checked.
Does the output contain buyer contact persons or emails? No — by design. The API request itself never asks for those fields. You get the buying organization's name and the official notice link; contact details are on the notice page if you need them for a bid.
Which countries does this cover? All EU member states plus EEA and several
enlargement/neighbourhood countries — anything published on TED. Filter with
countries (buyer's country) or nutsCodes (where the work is performed).
Can I monitor several profiles? Yes — one schedule per profile, same actor, same state store. Each profile keeps its own memory; they never interfere.
Do I need to write keywords in every language? No. TED translates titles into all 24 EU languages and the search covers all of them — "software" matches a Polish notice. Descriptions are the exception (source language only), which is why CPV codes are the recommended primary filter.
What about tenders below the EU thresholds? They are published on national portals, not TED, and are out of this actor's scope by design.
What is a corrigendum alert? Buyers amend notices — deadline moves, changed
lots. With alertOn: "new-and-updated" you get those as isUpdate: true items;
with the default you never hear about them (but they are remembered).
Troubleshooting
- "The profile matches all of TED (~3,500 notices/day)" — add at least one of
keywords,cpvCodes,countriesornutsCodes. - "TED rejected the search query" — usually a malformed filter value; check CPV codes are digits and country codes are real ISO codes.
- "Monitor state record … is not readable" — the state was written by a newer
version; run once with
resetState: trueto start a fresh baseline. - "Coverage truncated by the per-run request budget" — the profile matched
more than ~10,000 notices in one window; narrow it or lower
lookbackDays.
Something else off? Open an issue on the actor's Issues tab — reports are read and answered.