NL Tender Radar - Dutch Tenders from TED + TenderNed, Only New avatar

NL Tender Radar - Dutch Tenders from TED + TenderNed, Only New

Pricing

from $2.00 / 1,000 notices

Go to Apify Store
NL Tender Radar - Dutch Tenders from TED + TenderNed, Only New

NL Tender Radar - Dutch Tenders from TED + TenderNed, Only New

All Dutch public tenders in one feed: TED (EU) and TenderNed (NL) combined and de-duplicated, with only notices you have not seen before. Filter by date, CPV code and keywords. Clean, flat JSON with English field names; contact details removed (GDPR). Pay per notice; optional AI summary per notice.

Pricing

from $2.00 / 1,000 notices

Rating

0.0

(0)

Developer

Jishnu Harinandansingh

Jishnu Harinandansingh

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Categories

Security

Limited permissions

Share

NL Tender Radar – Dutch Tenders from TED + TenderNed, Only New

All Dutch public procurement notices in one feed. The Actor combines TED (Tenders Electronic Daily, the EU's official journal for tenders) and TenderNed (the Dutch national tender platform). A notice that is published in both appears once. With a daily schedule, each run returns only the notices you have not received before.

You can filter by publication date, CPV code and keywords. Each notice is one flat JSON item with stable English field names, ready for spreadsheets, CRMs or a tender-alert workflow. Contact persons, e-mail addresses and phone numbers are removed (GDPR).

What it does

  • Reads the official TED Search API (buyers in the Netherlands by default) and TenderNed's public JSON web service. Both are used without a login. The Actor does not scrape HTML.
  • Covers EU notices above the EU thresholds (on both platforms) and national Dutch notices below them (TenderNed only): contract notices, awards, prior information notices, market consultations, corrections and modifications.
  • De-duplicates the two feeds on the TED publication number (see below).
  • Only new: remembers which notices earlier runs returned and skips them (see below).
  • Returns notices newest first (by publication date).

Input

FieldTypeDefaultDescription
sourceslist["ted", "tenderned"]Which feeds to include.
lastDaysinteger7Notices published in the last N days. Ignored when publishedFrom is set.
publishedFromdate YYYY-MM-DD–Start of the publication date range.
publishedTodate YYYY-MM-DD–End of the range (inclusive). Empty means up to today.
cpvCodeslist[]CPV codes; sub-codes match too. 72000000 or 72 (IT services) also matches 72260000. At least 2 digits; the check digit (-5) is optional.
keywordslist[]Free-text search. A notice matches if it contains any keyword. Dutch works best for TenderNed. Max 20.
maxItemsinteger100Maximum number of notices returned per run (1–10,000).
onlyNewbooleantrueSkip notices already returned by earlier runs that used the same stateStoreName.
resetSeenbooleanfalseForget all notices returned before. With onlyNew on, this run returns everything in the date range and becomes the new starting point.
stateStoreNamestringnl-tender-radar-stateName of the key-value store that remembers returned notices. Use one name per search profile (radar-it, radar-cleaning, ...) so profiles do not hide each other's notices. Letters, digits and hyphens.
seenRetentionDaysinteger90Remembered notices published more than N days ago are forgotten, so the store stays small. Notices inside the current date range are kept, up to a cap of 100,000 remembered ids (oldest dropped first).
tedCountrieslist["NL"]Buyer countries for the TED feed (ISO codes, e.g. NL, BE). TenderNed always covers Dutch notices.
enrichbooleanfalseAdd AI fields to each notice: English summary, sector, key requirements. See AI enrichment.
maxEnrichedNoticesinteger10Only the first N notices of a run (newest first) are enriched (1–1,000).

Example: a daily alert for new IT tenders:

{
"lastDays": 3,
"cpvCodes": ["72"],
"maxItems": 500,
"onlyNew": true,
"stateStoreName": "radar-it"
}

Schedule it once a day. lastDays: 3 gives some overlap, so a late or failed run misses nothing, and onlyNew makes sure you still get each notice only once.

Output

One item per notice. Real example of a notice found in both feeds (published 2026-10-30):

{
"noticeId": "754284-2026",
"sources": [
"ted",
"tenderned"
],
"tedNoticeId": "754284-2026",
"tenderNedNoticeId": "446753",
"tenderId": "613963",
"noticeUrl": "https://ted.europa.eu/en/notice/-/detail/754284-2026",
"pdfUrl": "https://ted.europa.eu/en/notice/754284-2026/pdf",
"tedUrl": "https://ted.europa.eu/en/notice/-/detail/754284-2026",
"tenderNedUrl": "https://www.tenderned.nl/aankondigingen/overzicht/446753",
"title": "Integraal Maaien 2027-2030",
"titleEnglish": "Netherlands – Horticultural services – Integraal Maaien 2027-2030",
"buyerName": "Gemeente Krimpenerwaard",
"buyerCity": "STOLWIJK",
"buyerCountry": "NL",
"cpvCodes": [
"77300000",
"45233229"
],
"mainCpvCode": "77300000",
"estimatedValue": null,
"currency": null,
"publicationDate": "2026-10-30",
"deadline": "2026-11-04T12:00:00+01:00",
"procedureType": "open",
"noticeType": "correction",
"contractType": "services",
"european": true,
"placeOfPerformance": [
"NL"
],
"description": "Maaien grasvelden Maaien bermen Maaien watergangen Verkeersmaatregelen Maaien grasvelden - 462.800 m2 Maaien bermen - 244.603 m2 Maaien watergangen - 134.149 m2 Verkeersmaatregelen",
"documentsUrl": "https://www.tenderned.nl/aankondigingen/overzicht/446753",
"tenderPlatform": null,
"source": "TED - Tenders Electronic Daily (https://ted.europa.eu); TenderNed (https://www.tenderned.nl), CC0 1.0",
"attribution": "Contains data from TED - Tenders Electronic Daily (https://ted.europa.eu), (c) European Union, reused under Commission Decision 2011/833/EU and CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). Changes: fields selected, reformatted and merged with TenderNed data, notice types and country codes mapped, contact details removed."
}
FieldNotes
noticeIdThe TED publication number (123456-2026) when the notice is on TED, otherwise the TenderNed publication ID (447002). Unique within the feed.
sources["ted"], ["tenderned"] or ["ted", "tenderned"]: which feeds this notice came from.
tedNoticeId, tenderNedNoticeIdThe ID in each feed, or null. A TenderNed-only item can still have a tedNoticeId when its TED notice was outside this run (e.g. older or not yet indexed by TED).
tenderIdTenderNed "kenmerk", shared by all publications of one tender (notice, corrections, award). TenderNed only.
noticeUrl, pdfUrlNotice page and PDF: on TED when the notice is on TED, otherwise on TenderNed. tedUrl and tenderNedUrl give both links when available.
title, buyerName, descriptionOriginal language (mostly Dutch). E-mail addresses and phone numbers are redacted. titleEnglish (TED only) is TED's English summary title.
buyerCity, buyerCountryFrom TED; null for TenderNed-only notices.
cpvCodes, mainCpvCode8-digit CPV codes without check digit. mainCpvCode comes from TenderNed.
estimatedValue, currencyFrom TED (TenderNed does not publish values). Placeholder values of 0 or 1 are dropped.
deadlineTender submission deadline, ISO 8601 with time zone when known. null for most awards.
procedureTypeopen, restricted, neg-w-call, neg-wo-call, comp-dial, innovation, ... (TED eForms codes; TenderNed values use the same codes), plus TenderNed's private, open-house, market-consultation, specific-contract.
noticeTypecontract-notice, award-notice, prior-information, market-consultation, correction, modification, early-termination. TED eForms codes are mapped to these (cn-* → contract-notice, can-* and veat → award-notice, pin-* → prior-information, pmc → market-consultation, can-modif → modification); unknown codes pass through unchanged.
contractTypeworks, supplies or services.
europeanTenderNed: true for procedures above EU thresholds, false for national ones. null for TED-only notices.
placeOfPerformanceNUTS codes (NL33) or country codes (NL).
documentsUrl, tenderPlatformWhere the tender documents are, e.g. Mercell or Negometrix.
sourceData source(s) and license.
attributionRequired TED credit (CC BY 4.0) and list of changes, on every item with TED data; null for TenderNed-only items.

How de-duplication works

EU notices are usually published on both platforms. Each TenderNed publication carries the TED publication number of its TED copy (tedNoticeId). The Actor normalises both numbers (trims spaces and leading zeros, so 00012345-2026 equals 12345-2026) and merges a TED notice with the newest TenderNed publication that has its number.

Which fields win: for fields both feeds have (title, buyer, CPV codes, dates, deadline, procedure, notice and contract type, place, description, documents link), TED wins when it has a value. TED is the official EU publication with structured data, and TED-only notices then look the same as merged ones. TenderNed fills the fields TED left empty (often the description) and adds its own fields (tenderNedNoticeId, tenderId, mainCpvCode, european, tenderPlatform, tenderNedUrl). noticeUrl and pdfUrl point to TED. One exception: noticeType comes from TenderNed. TED reports a change notice under its original type (cn-standard), while TenderNed marks it correction or early-termination (74 of 365 merged notices in the live sample below).

Limits: a match is only possible when both copies are found in the same run. Each feed is fetched newest first up to maxItems, so when maxItems is smaller than the number of notices in the date range, the two feeds can cover different days and fewer duplicates are merged (the log then shows a warning). For a daily schedule, set maxItems above the daily volume (roughly 100 TED + 100 TenderNed notices per working day for NL). TED notices can show up a day before or after TenderNed. The overlap in lastDays and the only-new memory (which stores both IDs of a merged notice) cover most of this. A TenderNed notice delivered before its TED number was known can come back once as a TED item.

On live data from 2026-10-26 to 2026-10-30 (all notices, NL buyers on TED): 468 TED and 482 TenderNed notices, 365 of them in both feeds, so 585 items instead of 950. All 365 TED numbers on TenderNed matched exactly; no padded or otherwise different IDs were seen. In 88 of the 365, the two feeds give a different publication date (TED's is used).

How "only new" works

  • After each run, the Actor saves the IDs of every notice it returned (ted:<number> and/or tenderned:<id>) in a named key-value store (stateStoreName). Named stores persist between runs.
  • The next run skips any notice whose TED or TenderNed ID is in that list, including a TenderNed copy of a TED notice you already received. Already-seen TenderNed publications are dropped before their details are downloaded, so repeat runs are fast. (A TenderNed copy of a TED notice you received is only recognised after its details are downloaded; it is skipped and does not count towards maxItems.)
  • Only notices actually written to the dataset are remembered. If a run stops at maxItems or at your maximum charge, the rest come in the next run.
  • The list is pruned at the end of each run: IDs of notices published more than seenRetentionDays ago are dropped, except notices inside the run's date range, and the list is capped at 100,000 IDs.
  • onlyNew: false returns everything and leaves the list untouched. resetSeen: true clears it.
  • Runs that share a store should not run at the same time; the last one to finish wins.
  • If a source fails, the run fails before anything is written, and the list is unchanged.
  • If the stored list cannot be read (e.g. the store holds something else), the run fails instead of returning and charging everything again; set resetSeen or use another name.

AI enrichment

With enrich: true, each notice gets four extra fields. Notices are enriched newest first, up to maxEnrichedNotices per run.

FieldWhatHow
ai_summary2–3 sentences in English: what is bought, by which organisation, value and deadline when the notice states them.Claude Haiku 5.5 (Anthropic)
sectorOne of ~20 English sector labels (e.g. IT & telecom, Construction & works), from the main CPV code.Fixed lookup table, no AI
key_requirementsUp to 5 items {type, requirement, quote}: selection criteria, certifications, turnover or experience thresholds, award criteria. type is selection_criterion, certification, turnover, experience, award_criterion or other.Claude; every quote is checked to occur verbatim in the notice text, and items whose quote is not found are dropped
ai_metamodel, generated_at, disclaimer, skipped, enrichment_truncated–

Example (real TED notice, 2026-11-02, fields added to the item above):

{
"ai_summary": "Gemeente Deventer is tendering a multi-year contract for cleaning and inspecting the main sewer systems of Deventer, Olst-Wijhe and Raalte, split into three lots. Annual budgets are about €300,000 (Deventer), €50,000 (Olst-Wijhe) and €120,000 (Raalte), with ceiling amounts over four years of €1,800,000, €300,000 and €720,000 respectively. The submission deadline is 10 December 2026 at 14:30 (+01:00); the award is based on the lowest price.",
"sector": "Cleaning, waste & environment",
"key_requirements": [
{
"type": "award_criterion",
"requirement": "Award on the basis of the lowest price",
"quote": "Laagste prijs: De opdracht wordt gegund op grond van de laagste prijs."
}
],
"ai_meta": {
"model": "claude-haiku-5-5",
"generated_at": "2026-11-02T17:37:24+00:00",
"disclaimer": "AI-generated from the notice; may contain errors",
"skipped": null,
"enrichment_truncated": false
}
}

Disclaimer: ai_summary and key_requirements are AI-generated from the notice and may contain errors. Always check the original notice (noticeUrl) before you bid. The original fields are never changed; for TED data the AI fields are derived content (CC BY 4.0, changes marked by ai_meta).

Notices without AI fields. When a notice is not enriched, ai_summary and key_requirements are null (sector is still set) and ai_meta.skipped says why:

  • run_cap: beyond maxEnrichedNotices for this run.
  • monthly_budget: the Actor's monthly AI budget is used up (see below).
  • charge_limit: your maximum cost per run cannot cover the enrichment fee for this notice.
  • llm_error: the AI call failed for this notice (after one retry) or returned unusable output.

You only pay the enrichment fee for notices that were actually enriched (skipped is null). If every AI call of a run fails, the run is marked as failed (the base notices are still in the dataset).

What is sent to the AI. Only these notice fields: title, description, lot titles and descriptions, CPV codes, estimated value, deadline, selection and award criteria (lots and criteria fetched from TED for TED notices) and the buyer organisation name. Never sent: contact points, contact-person fields, addresses (other than what the description itself says), links. E-mail addresses and phone numbers are removed from all text before the call. Very long notices are cut to about 10,000 tokens (ai_meta.enrichment_truncated: true). Personal names that buyers type into free text cannot be detected reliably, so such a name can reach the AI provider (Anthropic, as processor; API data is not used for training) and, rarely, the summary. The AI only returns schema-constrained JSON and has no tools.

Cost guards. Besides your maxEnrichedNotices, the Actor keeps a monthly budget for its own AI spend (€15 per calendar month, UTC). It records the actual cost of each call from the token usage and checks the total before every call; once the budget is reached, enrichment stops until the next month (skipped: "monthly_budget", warning in the log) while base notices are still returned and charged at the base price. Each run logs its token usage and AI cost.

Speed: one AI call per enriched notice, about 2–6 seconds each, one at a time.

Pricing

Pay per result: $0.002 per notice (launch price, event notice). A notice found in both feeds is one item and costs $0.002 once. 1,000 notices cost $2. You only pay for notices written to the dataset; repeat runs with onlyNew only charge for new notices. Set maxItems or a maximum cost per run to cap spend. When the maximum cost per run is lower than maxItems, the Actor fetches only as many notices as it can charge for.

AI enrichment: $0.006 per enriched notice on top of $0.002 (event notice-enriched), so $0.008 for an enriched notice. 100 enriched notices cost $0.80. Only notices that were actually enriched are charged the extra fee. With a maximum cost per run, a notice is only enriched while the remaining budget covers both fees.

Limits and notes

  • Personal data: contact fields are never requested from either source. E-mail addresses and phone numbers that buyers type into free text are replaced with [email redacted] and [phone redacted]. Personal names in free text cannot be detected reliably, so they may remain. If you spot personal data in the output, report it in the Issues tab of this Actor and the redaction will be extended.
  • Speed: neither source publishes rate limits. The Actor sends at most one TED request per 1.5 s (250 notices each) and one TenderNed request per second, plus one TenderNed request per notice for details (CPV codes, places, TED number). 100 TenderNed notices take about 2 minutes. The two sources are fetched in parallel.
  • Max 10,000 notices per run, and TenderNed returns at most 10,000 results per search. For bigger backfills, run several date ranges.
  • Keywords and CPV codes are passed to each source's own search, so matching can differ slightly: TED searches all language versions, TenderNed searches a multi-word keyword as an exact phrase.
  • The date filter applies to the publication date.
  • TED and TenderNed may change their services. When a response format changes, the Actor fails with a clear error instead of returning an empty or partial dataset.
  • This is not an official TED, EU or Dutch government product.

Data sources and licenses

  • TED – ted.europa.eu, (c) European Union. Notices may be reused for commercial and non-commercial purposes (Commission Decision 2011/833/EU, CC BY 4.0). Each item with TED data names the source and the changes made in attribution.
  • TenderNed – tenderned.nl, open data under CC0 1.0.