# EU Tender & Contract Award Monitor (`nordicdataforge/eu-tender-contract-award-monitor`) Actor

Find and monitor EU public procurement opportunities and contract awards from the official TED API, with country, CPV, keyword, date, and deadline filters.

- **URL**: https://apify.com/nordicdataforge/eu-tender-contract-award-monitor.md
- **Developed by:** [Nordic Data Forge](https://apify.com/nordicdataforge) (community)
- **Categories:** Automation, Lead generation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 procurement 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## EU Tender & Contract Award Monitor

Turn official European public-procurement notices into a clean, schedulable opportunity and award feed. The Actor uses the European Union's public TED Search API directly. It needs no source login, API key, browser automation, CAPTCHA solving, or proxy.

Press **Start** with no configuration to receive up to 100 active tender opportunities published during the last 30 days. Add filters only when you need them.

### What you get

- Active tender opportunities or recent contract awards
- Buyer names and countries
- CPV product and service codes
- Publication and submission dates
- Estimated and awarded values when published
- Winner names for award notices when published
- Official TED HTML and XML links
- Cross-run `new`, `updated`, and `unchanged` status
- A machine-readable run summary

The Actor intentionally excludes named contact people and personal email addresses. It processes public procurement and organisation data only.

### Typical use cases

- Feed a B2G sales pipeline with new public-sector opportunities
- Monitor a CPV sector across one or more European countries
- Track competitors and buyers through contract-award notices
- Build a tender newsletter or internal alerting workflow
- Export normalized TED data to Sheets, a database, CRM, webhook, or Make/Zapier flow

### Example input

```json
{
    "mode": "opportunities",
    "maxResults": 250,
    "countries": ["DNK", "SWE", "DEU"],
    "cpvCodes": ["72", "48"],
    "keywords": ["cloud services", "cybersecurity"],
    "publishedWithinDays": 14,
    "enableChangeMonitoring": true,
    "outputMode": "new-and-updated"
}
```

Use ISO alpha-3 country codes such as `DNK`, `SWE`, `DEU`, `FRA`, or `NLD`. A short CPV prefix selects a sector tree: `72` matches IT services while an eight-digit code such as `72000000` is exact.

### Example output

```json
{
    "id": "1d3d32ceaf2f809aef0b1e81",
    "publicationNumber": "530123-2026",
    "noticeIdentifier": "8d3a6e77-example",
    "noticeCategory": "opportunity",
    "noticeType": "cn-standard",
    "noticeSubtype": "16",
    "title": "Denmark – IT services – Cloud operations platform",
    "description": "Operation and support of a cloud platform.",
    "buyerNames": ["Example public authority"],
    "buyerCountries": ["DNK"],
    "buyerCities": ["Copenhagen"],
    "cpvCodes": ["72000000"],
    "placeOfPerformanceCountries": ["DNK"],
    "placeOfPerformanceCities": ["Copenhagen"],
    "procedureType": "open",
    "contractNature": "services",
    "publicationDate": "2026-07-31",
    "dispatchDate": "2026-07-30",
    "submissionDeadlines": ["2026-09-01"],
    "nextSubmissionDeadline": "2026-09-01",
    "estimatedValue": 5000000,
    "estimatedValueCurrency": "EUR",
    "awardedValue": null,
    "awardedValueCurrency": null,
    "winnerNames": [],
    "winnerCountries": [],
    "submissionUrls": ["https://example.eu/tender"],
    "selectedLanguage": "ENG",
    "availableLanguages": ["DAN"],
    "sourceUrl": "https://ted.europa.eu/en/notice/-/detail/530123-2026",
    "xmlUrl": "https://ted.europa.eu/en/notice/530123-2026/xml",
    "sourceSystem": "TED — Tenders Electronic Daily",
    "sourceAttribution": "European Union — TED (Tenders Electronic Daily)",
    "sourceLicenceUrl": "https://ted.europa.eu/en/legal-notice",
    "firstSeenAt": "2026-07-31T12:00:00.000Z",
    "lastSeenAt": "2026-07-31T12:00:00.000Z",
    "changeType": "new",
    "changedFields": [],
    "scrapedAt": "2026-07-31T12:00:00.000Z"
}
```

Fields remain present with `null` or an empty array when TED did not publish that information. Value fields represent the procedure-level value when available, otherwise the first published lot-level value. Always consult the official notice before making a bid or compliance decision.

### Change monitoring

History is stored in an Apify named key-value store and is scoped to the filter configuration. It is not tied to a local machine.

- First equivalent run: every returned record is `new`.
- Later equivalent runs: records are `updated` when normalized content changes, otherwise `unchanged`.
- `changedFields` lists the exact normalized fields that changed.
- `new-and-updated` is the recommended output mode for a scheduled monitor.

The Actor does not label notices as “removed.” A notice can legitimately leave an active or rolling result window because its deadline passed or its publication date moved outside the window; reporting that as deletion would be misleading.

### Recommended schedule

Create an Apify schedule that runs once each weekday after the TED daily release. Keep `publishedWithinDays` unchanged and select `new-and-updated` after the initial run. Apify integrations can then send dataset items to your downstream system without manual work.

### Pricing proposal

The intended Store pricing is Pay per event:

- `apify-actor-start`: **Apify's recommended default $0.00005 event price**
- `result-item`: **$0.003 per delivered result after the first 25 results in each run**
- First 25 delivered records per run: **free**

No result event is charged for invalid upstream records, duplicates, errors, or records not pushed to the dataset. Platform usage generated during the run is included in the event price; ordinary post-run storage and data-retention rules still follow the user's Apify plan.

### Source, licence, and responsible use

Data comes from the official [TED Search API](https://docs.ted.europa.eu/api/latest/search.html). The [TED legal notice](https://ted.europa.eu/en/legal-notice) states that procurement notices published in the Supplement to the Official Journal may, unless otherwise indicated, be reused for commercial or non-commercial purposes. Editorial material is generally licensed under CC BY 4.0. Every record therefore includes source attribution and a link to the applicable legal notice.

This Actor is an independent product by Nordic Data Forge. It is not affiliated with or endorsed by TED, the Publications Office, or the European Union. It does not use EU or TED logos. Users remain responsible for verifying notice details, individual third-party rights, and the rules applicable to their own downstream use.

### Limits and data quality

- TED values are only returned when the publishing authority supplied and exposed them.
- A notice can contain many lots. Top-level arrays are deduplicated; scalar value fields prefer procedure-level data.
- The API documents a maximum of 250 notices and 10,000 selected fields per page. This Actor stays within both limits.
- All-history pagination has a 15,000-notice API ceiling; this Actor's maximum output is 5,000 per run.
- TED may update its field catalogue without changing the API major version. The Actor validates response shape and fails clearly rather than silently emitting corrupt data.
- Upstream availability and publication timing are outside the Actor author's control.

### FAQ

#### Do I need a TED account or API key?

No. TED documents the public Search API as unauthenticated and intended for data reusers.

#### Do I need a proxy?

No. The Actor calls the official API directly and uses conservative paging and retries.

#### Why are some values, winners, or deadlines empty?

They were not present in the selected notice, or the notice type does not contain them. Opportunity notices normally have deadlines; award notices are more likely to contain winners and awarded values.

#### Can I use an exact TED expert query?

Yes. Add a clause in `advancedQuery`; the Actor safely combines it with its date and mode filters. Invalid expert syntax is returned as a clear TED API error.

#### How do I export the data?

Use Apify's dataset export in JSON, CSV, Excel, XML, or RSS, or connect the dataset to a webhook/integration.

# Actor input Schema

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

Open opportunities is the best default for sales and bid monitoring. Awards add winner and awarded-value intelligence.

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

Maximum number of normalized notices fetched before change filtering.

## `publishedWithinDays` (type: `integer`):

Used when Published since is blank. The default searches the most recent 30 days on every scheduled run.

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

Optional ISO alpha-3 codes, for example DNK, SWE, DEU, FRA, or NLD. Leave empty for all countries.

## `cpvCodes` (type: `array`):

Enter a 2–8 digit CPV prefix or exact code. Example: 72 for IT services, 48 for software, or 72000000.

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

Optional full-text terms. Multiple entries match any term, for example cybersecurity, cloud services, or solar.

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

Optional fixed YYYY-MM-DD date. Overrides the recent publication window.

## `publishedUntil` (type: `string`):

Optional inclusive YYYY-MM-DD end date.

## `deadlineFrom` (type: `string`):

Optional inclusive YYYY-MM-DD deadline filter.

## `deadlineUntil` (type: `string`):

Optional inclusive YYYY-MM-DD deadline filter.

## `enableChangeMonitoring` (type: `boolean`):

Compare each result with the previous run of the same filter set in persistent Apify storage.

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

On the first run every record is new. Later runs can emit only actionable deltas.

## `preferredLanguage` (type: `string`):

ISO alpha-3 TED language code used for multilingual text, for example ENG, DAN, DEU, or FRA. Falls back gracefully.

## `advancedQuery` (type: `string`):

Optional advanced clause appended with AND. Use only if you know TED Expert Search syntax.

## `pageSize` (type: `integer`):

TED permits up to 250 notices per request and 10,000 returned fields per page.

## `requestTimeoutSecs` (type: `integer`):

Timeout for each official API request.

## `maxRetries` (type: `integer`):

Retries temporary timeouts, rate limits, and server errors with exponential backoff.

## `minRequestIntervalMillis` (type: `integer`):

Conservative pause between API pages.

## Actor input object example

```json
{
  "mode": "opportunities",
  "maxResults": 100,
  "publishedWithinDays": 30,
  "countries": [],
  "cpvCodes": [],
  "keywords": [],
  "enableChangeMonitoring": true,
  "outputMode": "all",
  "preferredLanguage": "ENG",
  "pageSize": 200,
  "requestTimeoutSecs": 45,
  "maxRetries": 3,
  "minRequestIntervalMillis": 250
}
```

# Actor output Schema

## `results` (type: `string`):

Normalized current notices and change metadata.

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

Query, source counts, delivery status, and change totals.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("nordicdataforge/eu-tender-contract-award-monitor").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("nordicdataforge/eu-tender-contract-award-monitor").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{}' |
apify call nordicdataforge/eu-tender-contract-award-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=nordicdataforge/eu-tender-contract-award-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/vj3Z5DxJNV7s6sJ9f/builds/YprOqp2gmLY9WH7Kz/openapi.json
