# EU + NL Tender Alert Feed (TED + TenderNed) (`kayorama/eu-tender-alert-feed`) Actor

Filtered public tender alerts from official TED (EU) and TenderNed (Netherlands) APIs. Filter by country, CPV sector and keywords. Dedup across sources. Organisation-level fields only, no personal data.

- **URL**: https://apify.com/kayorama/eu-tender-alert-feed.md
- **Developed by:** [Kayorama](https://apify.com/kayorama) (community)
- **Categories:** Business, Lead generation, Other
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 tender results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## EU + NL Tender Alert Feed (TED + TenderNed)

Most Store Actors stop at TED. This one also reads TenderNed, so you get Dutch national notices below the EU threshold next to the TED ones, already filtered to your sector and merged when the same procedure shows up in both places.

It uses the official TED Search API and the TenderNed public TNS webservice. No HTML scraping, no login, no personal contact fields.

### Good for

- Bid / BD teams who want a weekly list of open tenders in one sector
- NL IT, construction or facilities firms that miss national TenderNed notices when they only watch TED
- Anyone who wants clean rows for a CRM, newsletter or dashboard instead of raw API dumps

### What you get

One row per matched open tender after dedup:

| Field | Example |
| --- | --- |
| `title`, `titleEn` | Cloud workplace services for municipality X |
| `buyer`, `buyerCity`, `country` | Gemeente Utrecht, Utrecht, Netherlands |
| `cpvMain`, `cpvAll`, `cpvLabel`, `sector` | 72000000, IT services |
| `published`, `deadline`, `daysLeft`, `closingSoon` | 2026-10-28, 2026-11-20, 16, true |
| `valueEur` | 450000 (from TED when published; TenderNed often has none) |
| `sources` | TenderNed, TED, or TenderNed + TED |
| `isNew` | true when trackChanges is on and the tender was not seen before |
| `url`, `tedUrl`, `tendernedUrl` | Links to the official notice pages |
| `matchReason` | Why it passed your CPV / keyword filter |
| `description` | Short scrubbed summary (emails, phones and named contacts removed) |

A `SUMMARY` record in the run key-value store lists counts, source queries and attribution.

### Example input

```json
{
  "sources": ["ted", "tenderned"],
  "buyerCountries": ["NLD"],
  "noticeTypes": ["contract"],
  "lookbackDays": 14,
  "cpvPrefixes": ["72", "48"],
  "includeKeywords": ["software", "saas", "cloud", "ict"],
  "matchMode": "cpv_or_keyword",
  "trackChanges": true,
  "outputMode": "all"
}
```

Tips:

- Keep `NLD` in `buyerCountries` whenever TenderNed is selected.
- Use `matchMode: "cpv"` with a short CPV list for big countries (DEU, FRA) so TED can filter on the server.
- Schedule a weekly run with `lookbackDays: 7` and `outputMode: "newOnly"` for an alert feed.

### Data and privacy

- TED: credit the Publications Office of the European Union. Reuse is allowed, including commercially, under Commission Decision 2011/833/EU. Do not distort the notices.
- TenderNed: public TNS data, owner PIANOo, CC-0 1.0 on data.overheid.nl. The service can change without notice.
- Only organisation-level fields are requested. Free text is scrubbed for e-mail addresses, phone numbers and named contact persons.

### Pricing

Pay per event: you pay for each matched tender row written to the dataset, plus the standard Actor start event. See the Pricing tab for current rates. Set a max total charge on the run if you want a hard budget.

### Done-for-you option

If you want a weekly Excel, digest PDF and e-mail draft instead of running the Actor yourself, that is a separate service at https://studio.kayorama.nl/tender-alert-feed.

# Actor input Schema

## `sources` (type: `array`):

Official open APIs to read. TenderNed only covers the Netherlands, so NLD must be in buyer countries when TenderNed is selected.

## `buyerCountries` (type: `array`):

TED buyer countries, e.g. NLD, BEL, DEU. Add NLD when you want TenderNed national notices below the EU threshold.

## `noticeTypes` (type: `array`):

Contract notices are calls for tender. Market consultations are early PIN / MAC notices.

## `lookbackDays` (type: `integer`):

Publication window counted back from today (or asOfDate). Use 7 for a weekly feed.

## `asOfDate` (type: `string`):

Optional run date YYYY-MM-DD. Defaults to today.

## `cpvPrefixes` (type: `array`):

2 to 8 digit CPV prefixes without check digit. Example: 72 = IT services, 48 = software, 45 = construction.

## `includeKeywords` (type: `array`):

NL or EN words matched at word start (so cloud also matches cloudoplossing). End a word with ! for whole-word only.

## `excludeKeywords` (type: `array`):

Drop notices that hit these words.

## `matchMode` (type: `string`):

cpv_or_keyword keeps notices that match either filter (recommended). cpv / keyword / cpv_and_keyword are stricter.

## `minValueEur` (type: `integer`):

Optional. Many Dutch notices publish no value; those stay unless keepUnknownValue is off.

## `maxValueEur` (type: `integer`):

Optional upper bound on estimated procedure value.

## `keepUnknownValue` (type: `boolean`):

Recommended on. TenderNed public data has no value field.

## `minDaysLeft` (type: `integer`):

Drop notices whose deadline is closer than this (0 keeps open notices including those closing today).

## `maxDaysLeft` (type: `integer`):

Optional. Drop notices whose deadline is farther out than this.

## `keepUnknownDeadline` (type: `boolean`):

Recommended on. Some notices publish no deadline yet.

## `closingSoonDays` (type: `integer`):

Mark closingSoon when days left are within this window.

## `trackChanges` (type: `boolean`):

Compare with the previous run in a named key-value store and set isNew. First run treats notices published in the last 7 days as new.

## `stateStoreName` (type: `string`):

Named key-value store that keeps seen tender IDs between runs when trackChanges is on.

## `outputMode` (type: `string`):

all = every matched open tender. newOnly = only tenders marked isNew (needs trackChanges).

## `maxResults` (type: `integer`):

Hard cap on rows pushed to the dataset (and billed). Leave empty for no extra cap beyond your pay-per-event budget.

## `tedMaxPages` (type: `integer`):

Safety cap. Each page is up to 250 notices before local filtering.

## `tendernedMaxPages` (type: `integer`):

Safety cap per notice type. Each page is up to 100 list rows; details are fetched (and cached) per notice.

## Actor input object example

```json
{
  "sources": [
    "ted",
    "tenderned"
  ],
  "buyerCountries": [
    "NLD"
  ],
  "noticeTypes": [
    "contract"
  ],
  "lookbackDays": 7,
  "cpvPrefixes": [
    "72",
    "48"
  ],
  "includeKeywords": [
    "software",
    "saas",
    "cloud",
    "ict"
  ],
  "matchMode": "cpv_or_keyword",
  "keepUnknownValue": true,
  "minDaysLeft": 0,
  "keepUnknownDeadline": true,
  "closingSoonDays": 14,
  "trackChanges": true,
  "stateStoreName": "eu-tender-alert-feed-state",
  "outputMode": "all",
  "tedMaxPages": 20,
  "tendernedMaxPages": 30
}
```

# Actor output Schema

## `tenders` (type: `string`):

One row per matched open tender after cross-source dedup.

## `summary` (type: `string`):

SUMMARY record with counts, source queries and attribution.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "sources": [
        "ted",
        "tenderned"
    ],
    "buyerCountries": [
        "NLD"
    ],
    "noticeTypes": [
        "contract"
    ],
    "cpvPrefixes": [
        "72",
        "48"
    ],
    "includeKeywords": [
        "software",
        "saas",
        "cloud",
        "ict"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("kayorama/eu-tender-alert-feed").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "sources": [
        "ted",
        "tenderned",
    ],
    "buyerCountries": ["NLD"],
    "noticeTypes": ["contract"],
    "cpvPrefixes": [
        "72",
        "48",
    ],
    "includeKeywords": [
        "software",
        "saas",
        "cloud",
        "ict",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("kayorama/eu-tender-alert-feed").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "sources": [
    "ted",
    "tenderned"
  ],
  "buyerCountries": [
    "NLD"
  ],
  "noticeTypes": [
    "contract"
  ],
  "cpvPrefixes": [
    "72",
    "48"
  ],
  "includeKeywords": [
    "software",
    "saas",
    "cloud",
    "ict"
  ]
}' |
apify call kayorama/eu-tender-alert-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kayorama/eu-tender-alert-feed"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Uaa143J4iAgC5wX2f/builds/9lrYmYEaZ3flHBcON/openapi.json
