# Public Tenders & Contract Awards Feed - EU, UK, NL (`luc-dts/tenders-awards-feed`) Actor

Tenders and contract awards from TED, UK Find a Tender, Contracts Finder and TenderNed in one schema. Filter by CPV, country, value; incremental mode.

- **URL**: https://apify.com/luc-dts/tenders-awards-feed.md
- **Developed by:** [Luc Dijkstra](https://apify.com/luc-dts) (community)
- **Features:** 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 delivered notice (not an award)s

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Public Tenders & Contract Awards Feed — EU, UK, NL

Get **public procurement tenders and contract awards** from official government sources in **one clean, consistent format**: TED (EU-wide), UK Find a Tender, UK Contracts Finder and TenderNed (Netherlands). Filter by CPV code, country, value, keywords and deadline. Schedule it and receive **only what is new or changed** since the last run.

Built for people who want to build their own tender alerts: bid managers, consultancies, suppliers to the public sector, market researchers, and n8n / Make / Zapier / AI-agent workflows. Uses official open data APIs only — no website scraping, no proxies, no login.

### What you get

- **One schema for four sources.** Every record has the same fields, whatever the source: title, buyer, country, CPV codes, contract type, procedure, value, publication date, deadline, link, and more.
- **Tenders *and* awards.** Planning notices, open tenders, contract awards (with winners and awarded value where the source publishes them), amendments, cancellations.
- **Alerts without extra tooling.** Incremental mode remembers what it already delivered: schedule the Actor (hourly, daily) and each run returns only new or updated notices, each marked `changeType: "new"` or `"updated"`.
- **Precise filters.** CPV prefix (for example `72` for IT services), buyer country, value range with currency, keywords, exclude keywords, deadline within N days.
- **English titles for EU notices.** TED notices include an English title next to the original.
- **Predictable cost.** You pay per delivered notice and you stay in control with a hard item limit and your own maximum charge per run.

### Sources

| Source | Coverage | Awards with winner and value | Notes |
|---|---|---|---|
| **TED** | All EU member states (plus EEA and some others) | Yes | Official EU Tenders Electronic Daily. Several thousand notices per day. |
| **UK Find a Tender** | United Kingdom, above-threshold procurement | Winner yes; value often | OCDS data. Many awards have no value in the source. |
| **UK Contracts Finder** | United Kingdom, lower-value and below-threshold notices | Yes | OCDS data. |
| **TenderNed** | Netherlands, including notices below the EU threshold | **No** (source does not publish winners or values) | EU-level Dutch notices also appear in TED; by default TenderNed adds only the national ones when TED is selected. |

More sources (for example US federal opportunities) may follow.

### Quick start

1. Open the **Input** tab and choose sources, stages and filters.
2. Click **Start**. The first run looks back 24 hours (change with *Published since*).
3. Open the **Dataset** tab, or fetch the results through the API.
4. For alerts, create a **Schedule** and keep *Mode* on *Incremental*.

#### Example: new IT and software tenders in the Netherlands and Germany

```json
{
  "sources": ["ted", "tenderned"],
  "stages": ["tender"],
  "countries": ["NL", "DE"],
  "cpvPrefixes": ["72", "48"],
  "mode": "incremental",
  "stateKey": "it-nl-de",
  "maxItems": 200
}
```

#### Example: who won large road-works contracts this week?

```json
{
  "sources": ["ted", "uk-fts", "uk-cf"],
  "stages": ["award"],
  "cpvPrefixes": ["4523"],
  "minValue": 1000000,
  "currency": "EUR",
  "mode": "window",
  "publishedSince": "7d",
  "maxItems": 1000
}
```

### Output

Each record looks like this (shortened):

```json
{
  "id": "ted:763830-2026",
  "changeType": "new",
  "source": "ted",
  "url": "https://ted.europa.eu/en/notice/-/detail/763830-2026",
  "stage": "award",
  "noticeType": "can-standard",
  "title": "Acord-cadru – „Intretinere curenta a partii carosabile, acostamente, benzi de urgenta si benzi de incadrare, anul I – IV” D.R.D.P. Iasi – Lot 1-6",
  "titleEn": "Romania – Highway maintenance work – Acord-cadru – „Intretinere curenta a partii carosabile, …",
  "buyer": { "name": "COMPANIA NATIONALA DE ADMINISTRARE A INFRASTRUCTURII RUTIERE S.A.", "country": "RO", "countries": ["RO"] },
  "cpv": { "main": "45233139", "all": ["45233139"] },
  "contractType": "works",
  "procedureType": "open",
  "value": { "amount": 59519780.3, "currency": "RON", "kind": "awarded" },
  "publishedAt": "2026-11-04",
  "deadlineAt": null,
  "award": { "winnerCount": 1, "winners": [{ "name": "ARTCON WAY S.R.L." }] },
  "dataWarnings": [],
  "attribution": "Contains public procurement notices from TED …"
}
```

| Field | Meaning |
|---|---|
| `id` | Stable ID: `<source>:<source id>` |
| `changeType` | `new`, or `updated` when a notice you received before has changed |
| `stage` | `planning`, `tender`, `award`, `contract`, `amendment`, `cancellation` |
| `title`, `titleEn` | Original title; English title where available |
| `buyer` | Name and ISO country of the contracting authority (joint procurements list all countries) |
| `cpv` | Main CPV code and all CPV codes (8 digits) |
| `value` | Amount, currency and whether it is `estimated` or `awarded`. **Never converted** between currencies |
| `publishedAt`, `deadlineAt`, `daysToDeadline` | Dates as `YYYY-MM-DD`. Some sources publish dates only, not times |
| `award` | Winners (names of companies) of award notices |
| `aboveEuThreshold` | Only where the source says so; otherwise `null` |
| `dataWarnings` | Notes about the source data, for example `no_award_details_in_source` |
| `attribution` | Required source attribution; keep it when you republish the data |

Each run also stores a `SUMMARY` record with the result per source (fetched, delivered, unchanged, errors).

### Pricing

Pay per delivered notice (see the **Pricing** tab for the current prices):

- **Tender notice**: every delivered notice except awards.
- **Award notice**: every delivered contract award notice.

You are only charged for notices that are actually delivered to your dataset: filtered, unchanged and failed notices are free. The run stops cleanly when your *maximum charge per run* is reached, and the next run continues with the rest.

### Using the data

- **Schedule** the Actor and connect a **webhook**, an **n8n / Make / Zapier** integration or the **Apify API** to be notified of new notices.
- Use it as a tool in an **AI agent** through Apify's MCP server.
- Call the API directly:
  `POST https://api.apify.com/v2/acts/<your-username>~tenders-awards-feed/runs` with the input as JSON body.

### Good to know

- Sources publish at different times; weekends are quiet.
- Values are exactly as published. Some notices have no value; filters on value drop those notices.
- Joint procurements can have buyers in several countries; a country filter matches if any buyer matches.
- `procedureType` uses the EU vocabulary (`open`, `restricted`, …) for TED and TenderNed, and the OCDS vocabulary (`open`, `selective`, `limited`, `direct`) for the UK.
- Keyword filters are applied after fetching: combine them with country or CPV filters on large result sets.
- Incremental state is kept for 14 days per monitor (same *State key* and same filters) in a key-value store in your account. Changing a filter starts a fresh monitor.
- To check that all sources are reachable, run the Actor with **Run health check** enabled. It delivers no notices and costs nothing.

### Data sources, licences and privacy

- **TED:** procurement notices of the European Union, published in the Supplement to the Official Journal; reuse is permitted under the TED legal notice. Credit: *TED (Tenders Electronic Daily), European Union*.
- **UK Find a Tender and Contracts Finder:** contains public sector information licensed under the Open Government Licence v3.0.
- **TenderNed:** publication data from the TenderNed open data service of the Dutch government.
- **Personal data:** the Actor never reads or stores contact persons, e-mail addresses or phone numbers from notices, and removes e-mail addresses from free-text descriptions. Award notices contain the names of winning companies, which can include sole traders; set *Omit winner names* if your use case must avoid this. You are responsible for how you use the data.
- This Actor is not affiliated with TED, the UK Cabinet Office or TenderNed. The data is provided as published by the sources, without guarantee of completeness or accuracy. It is not legal or procurement advice.

### Questions and feedback

Use the **Issues** tab of this Actor for questions, bugs and feature requests (for example additional countries or sources).

# Actor input Schema

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

Which official sources to query. TED = EU-wide (Tenders Electronic Daily). UK Find a Tender and Contracts Finder = United Kingdom. TenderNed = Netherlands.

## `stages` (type: `array`):

Which stage of the procurement process to return: planning (prior information), tender (open call), award (winner announced), contract, amendment, cancellation.

## `countries` (type: `array`):

ISO country codes of the contracting authority, for example NL, DE, FR, GB (alpha-2 or alpha-3). Empty = all countries. TED filters on the country; the UK sources (GB) and TenderNed (NL) are skipped when their country is not selected.

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

Match CPV codes that start with these digits, for example 72 (IT services) or 7222 (IT consultancy). Empty = all categories.

## `keywords` (type: `array`):

Keep notices whose title or description contains at least one of these words (case-insensitive). Applied after fetching, so combine with CPV or country filters for large result sets.

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

Drop notices whose title or description contains any of these words.

## `minValue` (type: `integer`):

Minimum estimated or awarded value in the notice's own currency. Notices without a value are dropped when a limit is set.

## `maxValue` (type: `integer`):

Maximum estimated or awarded value in the notice's own currency.

## `currency` (type: `string`):

Three-letter currency code (for example EUR or GBP). Values are never converted: only notices in this currency pass the value filter. Leave empty to compare numbers regardless of currency.

## `deadlineWithinDays` (type: `integer`):

Only notices whose submission deadline falls within the next N days. Notices without a deadline are dropped when this is set.

## `mode` (type: `string`):

incremental = only notices that are new or changed since the previous run of the same monitor (same state key and filters); schedule this Actor to get alerts. Each notice carries changeType 'new' or 'updated'. State is kept for 14 days in a key-value store of your account. window = everything published in the given period, no state.

## `publishedSince` (type: `string`):

Either a date (YYYY-MM-DD) or a relative period such as 24h or 7d. Default: 7d in window mode, 24h otherwise. In incremental mode it only sets the look-back of the very first run; later runs continue where the previous run stopped. TED publishes date-only, so the effective resolution is one day.

## `stateKey` (type: `string`):

Name of this monitor (letters, digits, dash, underscore). Different keys keep separate incremental state. Changing any filter also starts a fresh monitor.

## `maxItems` (type: `integer`):

Hard upper limit of notices returned in one run. Protects your budget.

## `includeDescription` (type: `boolean`):

Include the notice description (truncated to 2000 characters).

## `includeRaw` (type: `boolean`):

Attach the unmodified source record to each notice (larger output).

## `tenderNedScope` (type: `string`):

auto = when TED is also selected, TenderNed adds only national notices (below the EU threshold), because EU-level notices appear in TED with more detail; otherwise all TenderNed notices. all = every TenderNed notice (EU-level ones may duplicate TED). national = only notices below the EU threshold.

## `healthCheck` (type: `boolean`):

Checks every source with a tiny live request and reports whether the data still has the expected shape. Delivers no notices and costs nothing. The result is stored under the key HEALTHCHECK.

## `omitWinnerNames` (type: `boolean`):

Leave out winner names in award notices (the number of winners is still reported). Useful if your use case must avoid data about sole traders.

## Actor input object example

```json
{
  "sources": [
    "ted"
  ],
  "stages": [
    "tender",
    "award"
  ],
  "countries": [],
  "cpvPrefixes": [],
  "keywords": [],
  "excludeKeywords": [],
  "mode": "incremental",
  "stateKey": "default",
  "maxItems": 100,
  "includeDescription": true,
  "includeRaw": false,
  "tenderNedScope": "auto",
  "healthCheck": false,
  "omitWinnerNames": false
}
```

# Actor output Schema

## `notices` (type: `string`):

Tenders and contract awards in the unified schema, as a table with the most useful fields. Open the dataset for all fields and the export formats (JSON, CSV, Excel).

## `allFields` (type: `string`):

The same notices with every field: buyer, CPV codes, value, deadline, winners, data warnings and attribution.

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

Per source: status, records fetched, delivered, unchanged and skipped, the time window used, and how many notices were charged per event.

# 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"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("luc-dts/tenders-awards-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"] }

# Run the Actor and wait for it to finish
run = client.actor("luc-dts/tenders-awards-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"
  ]
}' |
apify call luc-dts/tenders-awards-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,luc-dts/tenders-awards-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/uZGbuaGLy4YmOrfkB/builds/bakGYiOMIKfbtZngy/openapi.json
