# EU Tenders API & TED Procurement Monitor (`xerophylous_mercy_0wn/eu-tender-radar`) Actor

Search and monitor official EU TED procurement notices by keyword, CPV code, buyer country, date, or expert query. Get normalized multilingual tender records, deadlines, direct document links, and only-new state for scheduled alerts.

- **URL**: https://apify.com/xerophylous\_mercy\_0wn/eu-tender-radar.md
- **Developed by:** [Hryhory Sinenka](https://apify.com/xerophylous_mercy_0wn) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 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 Search & Monitor

Find and monitor official European public-procurement notices from TED. Search by keyword, CPV code, buyer country, notice type, publication window, or a native TED expert query. Results are normalized into stable records for opportunity alerts, sales pipelines, market intelligence, and AI agents.

This Actor uses the European Union's public, no-authentication [TED Search API v3](https://docs.ted.europa.eu/api/latest/search.html). It does not scrape search-result pages.

### Why use it

- Search active EU procurement opportunities across countries and languages.
- Get one clean record per notice instead of TED's multilingual nested response.
- Monitor a query on a schedule and emit only notices not seen before.
- Start with a quiet baseline so the first scheduled run does not flood downstream systems.
- Preserve direct TED HTML, XML, and PDF links.
- Set hard result, page-size, timeout, retry, and run-price ceilings.

### Quick start

```json
{
  "keywords": ["laboratory reagents", "diagnostics"],
  "keywordMode": "any",
  "cpvCodes": ["33696500"],
  "buyerCountries": ["FRA", "DEU", "ESP"],
  "lookbackDays": 30,
  "scope": "ACTIVE",
  "onlyNew": true,
  "firstRunMode": "emit_recent",
  "maxResults": 100
}
```

For advanced cases, provide `expertQuery`. It replaces the structured query:

```json
{
  "expertQuery": "classification-cpv IN (33696500) AND buyer-country IN (FRA DEU ESP) SORT BY publication-date DESC",
  "scope": "ACTIVE",
  "maxResults": 250
}
```

### Output

Every dataset item is a normalized tender notice:

```json
{
  "schemaVersion": "eu-tender/1.0",
  "recordType": "tender_notice",
  "publicationNumber": "541897-2026",
  "title": "Spain – Laboratory reagents – ...",
  "buyerName": "Servicio Madrileño de Salud - Hospital Universitario La Paz",
  "buyerCountries": ["ESP"],
  "publicationDate": "2026-08-05+02:00",
  "submissionDeadline": "2026-09-03+02:00",
  "cpvCodes": ["33696500"],
  "noticeType": "cn-standard",
  "formType": "competition",
  "tedUrl": "https://ted.europa.eu/en/notice/-/detail/541897-2026",
  "deliveryId": "ted:541897-2026",
  "source": "TED Search API v3"
}
```

The `SUMMARY` key-value-store record contains the generated query, total matches reported by TED, fetched/emitted counts, pagination evidence, state mode, and truncation flags.

### Stateful monitoring

With `onlyNew: true`, the Actor stores publication numbers under a key derived from the query and `stateNamespace`. Later runs suppress seen notices. Use `firstRunMode: baseline_only` to record current matches without emitting them; future scheduled runs then return only new notices.

Delivery is **at least once**. Downstream systems should deduplicate with `deliveryId`.

### Scope and limitations

- Data comes from TED and inherits its availability, indexing, and source-data quality.
- Keyword matching uses TED's expert-search semantics, not a separate semantic model.
- Estimated values and deadlines can be absent or repeated across lots.
- `maxResults` is 5,000 per run. Use a narrower query or separate tasks for larger monitoring programs.
- This Actor discovers opportunities; it does not assess legal eligibility or submit bids.

### Source and attribution

Source: [TED Search API](https://docs.ted.europa.eu/api/latest/search.html), managed by the Publications Office of the European Union. TED states that the public Search API does not require authentication and is intended for reuse, including by commercial organizations building added-value services.

# Actor input Schema

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

Full-text terms to match across TED notices. Leave empty to search by the other filters.

## `keywordMode` (type: `string`):

Match any keyword or require all keywords.

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

Eight-digit Common Procurement Vocabulary codes, for example 33696500 for laboratory reagents.

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

Three-letter country codes used by TED, for example FRA, DEU, ESP, or ITA.

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

Optional TED notice-type codes such as cn-standard. Leave empty for all notice types.

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

Used when explicit publication dates are not provided.

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

Optional inclusive start date in YYYY-MM-DD format.

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

Optional inclusive end date in YYYY-MM-DD format. Defaults to today.

## `scope` (type: `string`):

Active notices are the best default for commercial opportunity monitoring.

## `expertQuery` (type: `string`):

Optional. When set, this replaces the structured query. Example: classification-cpv IN (33696500) AND buyer-country IN (FRA DEU).

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

TED language code used for titles, buyer names, and links. English is used as fallback.

## `onlyNew` (type: `boolean`):

Persist publication numbers and suppress repeats on scheduled runs.

## `firstRunMode` (type: `string`):

Emit the current matches or create a quiet baseline for future alerts.

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

Hard output and API pagination ceiling.

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

Notices requested per TED API page. TED allows at most 250.

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

Named Apify key-value store used for new-notice detection.

## `stateNamespace` (type: `string`):

Change this to maintain a separate baseline for the same search.

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

Total deadline for each request to the official TED Search API.

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

Retry timeouts, rate limits, and temporary TED server errors with bounded backoff.

## Actor input object example

```json
{
  "keywords": [
    "laboratory reagents"
  ],
  "keywordMode": "any",
  "cpvCodes": [],
  "buyerCountries": [],
  "noticeTypes": [],
  "lookbackDays": 30,
  "scope": "ACTIVE",
  "preferredLanguage": "eng",
  "onlyNew": true,
  "firstRunMode": "emit_recent",
  "maxResults": 100,
  "pageSize": 100,
  "stateStoreName": "eu-tender-radar-state",
  "stateNamespace": "default",
  "requestTimeoutSecs": 30,
  "maxRetries": 2
}
```

# Actor output Schema

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

New or matching EU procurement notices from the official TED Search API.

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

Query, counts, pagination, state, and truncation evidence for this run.

# 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 = {
    "keywords": [
        "laboratory reagents"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("xerophylous_mercy_0wn/eu-tender-radar").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 = { "keywords": ["laboratory reagents"] }

# Run the Actor and wait for it to finish
run = client.actor("xerophylous_mercy_0wn/eu-tender-radar").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 '{
  "keywords": [
    "laboratory reagents"
  ]
}' |
apify call xerophylous_mercy_0wn/eu-tender-radar --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/JHnTwBjnzxflGnAsY/builds/wTZR5y95jP6KCgshB/openapi.json
