# EU Tender Matcher (TED) – AI Fit Analysis (`vast_grouse/eu-tender-matcher`) Actor

Find open EU public tenders from TED that match your company. Filter by keyword, CPV code, country, value and deadline; get English titles, deadlines, values and an optional AI fit score with risks and requirements.

- **URL**: https://apify.com/vast_grouse/eu-tender-matcher.md
- **Developed by:** [Daisy Zhang](https://apify.com/vast_grouse) (community)
- **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 Tender Matcher (TED) – AI Fit Analysis

Find **open EU public tenders** that fit your company, in every EU/EEA country, from the official [TED](https://ted.europa.eu) database (Tenders Electronic Daily). Get English titles, deadlines and values for every tender. Optionally, an AI bid manager reads each tender against your company profile and tells you **whether to bid, why, and what could block you**.

### Why use it

- **One search across 30+ countries.** TED publishes ~800 new tenders every working day in 24 languages. This Actor filters them to the few that matter to you.
- **Only tenders you can still bid on.** Closed tenders, award notices and notices with deadlines too close are filtered out by default.
- **Bid language up front.** Every result lists the languages bids may be submitted in, so you can skip tenders you can't answer.
- **Ranked, not just listed.** Every result gets a relevance score from your keywords and categories.
- **AI fit analysis (optional).** For each tender: fit score 0–100, verdict, plain-language summary, why it fits, risks and barriers (local presence, language, certifications, turnover), key requirements, and the language bids must be submitted in. Works on tenders written in German, French, Polish or any other EU language.
- **Built for AI agents too.** Clean JSON output, callable through Apify's API and MCP server.

### Who it's for

- SMEs and consultancies looking for public-sector work abroad
- Bid and proposal managers who screen tenders every week
- B2B sales teams tracking public budgets in their category
- Agencies and tools that resell tender alerts

### Input

| Field | What it does |
|---|---|
| `keywords` | Words or phrases to look for (any of them). Add local-language terms for better recall, e.g. `cybersecurity`, `Penetrationstest`. |
| `requireKeywordMatch` | Drop tenders whose title and description mention none of your keywords. Default on. |
| `cpvCodes` | EU procurement category codes. Parents include children: `72000000` = all IT services. |
| `countries` | Buyer countries, 2 or 3 letters (`DE`, `FRA`). Empty = all. |
| `publishedWithinDays` | Look-back window. Default 14. |
| `onlyOpen` | Only tenders still accepting bids. Default on. |
| `minDaysToDeadline` | Skip tenders closing too soon to prepare a bid. |
| `minEstimatedValue` | Minimum published value (usually EUR). |
| `maxResults` | Default 50. |
| `companyProfile` | What you sell, where you deliver, size, certifications, languages. |
| `aiFitAnalysis` | Turn on AI fit analysis for each result. |
| `outputLanguage` | Language of the AI output. Default English. |

Example:

```json
{
  "keywords": ["cybersecurity", "penetration test", "Penetrationstest"],
  "countries": ["DE", "NL", "IE", "BE"],
  "minDaysToDeadline": 7,
  "companyProfile": "12-person cybersecurity firm in Dublin. Pen testing, red teaming, ISO 27001 consulting. English only.",
  "aiFitAnalysis": true
}
```

### Output

One item per tender:

```json
{
  "noticeId": "716155-2026",
  "url": "https://ted.europa.eu/en/notice/-/detail/716155-2026",
  "title": "Germany – Computer audit and testing services – Durchführung von Penetrationstests",
  "originalTitle": "Durchführung von Penetrationstests",
  "originalLanguage": "deu",
  "buyerName": "Medizinischer Dienst Westfalen-Lippe",
  "buyerCountry": "DEU",
  "placeOfPerformance": ["DEA33", "DEU"],
  "publicationDate": "2026-10-16",
  "deadline": "2026-11-16",
  "daysToDeadline": 30,
  "estimatedValue": null,
  "currency": null,
  "cpvCodes": ["72800000"],
  "procedureType": "open",
  "submissionLanguages": ["German"],
  "contractNature": ["services"],
  "lots": ["Durchführung von Penetrationstests"],
  "description": "Der Auftraggeber beabsichtigt ...",
  "relevanceScore": 38,
  "matchedKeywords": ["Penetrationstest"],
  "ai": {
    "fitScore": 72,
    "verdict": "possible_fit",
    "summary": "A regional health-insurance medical service wants network-based penetration tests of its internet-, WAN- and LAN-reachable systems.",
    "whyItFits": ["Core scope is network penetration testing, your main service"],
    "risksAndBarriers": ["Bid documents and communication are likely German-only"],
    "keyRequirements": ["Open procedure", "Services contract"],
    "submissionLanguage": "German"
  }
}
```

The `ai` values above are illustrative. The `ai` field appears only when AI fit analysis is on.

### Pricing

Pay per result, no subscription:

- **Tender result:** $3 per 1,000 tenders
- **AI fit analysis:** $0.03 per analysed tender

Set a maximum cost per run in Apify and the Actor stops before exceeding it. AI analysis runs first on the highest-ranked tenders.

### Tips

- Combine 2–3 English keywords with the same words in the target country's language.
- Use CPV codes for broad categories and keywords for niches.
- Schedule a daily run with `publishedWithinDays: 1` and connect it to email, Slack or a Google Sheet for a tender alert feed.

### Data source and limits

- Data comes from the official TED Search API of the Publications Office of the European Union. Notices are reused under the EU's open-data reuse policy. This Actor is not affiliated with the EU.
- Estimated values are only present when the buyer published one.
- AI fit analysis is processed by DeepSeek's API: your company profile and the tender text are sent to DeepSeek. Leave AI analysis off if that does not suit your data policy.
- AI analysis is decision support, not legal or bid advice. Always read the full tender documents before bidding.

# Actor input Schema

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

Words or phrases to look for in the tender text (any of them). English works across all countries because TED translates titles; add local-language terms for better recall, e.g. "cloud", "Rechenzentrum".

## `requireKeywordMatch` (type: `boolean`):

TED's search also matches words buried in attachments and legal boilerplate. When on, tenders whose title, lots and description mention none of your keywords are dropped. Turn off for maximum recall.

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

EU procurement category codes. Parent codes include their children: 72000000 = all IT services. Find codes at https://ted.europa.eu/en/simap/cpv

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

ISO country codes, 2 or 3 letters (DE or DEU, FR, NL...). Leave empty for all of Europe.

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

Only tenders published in this many recent days. Use 1 for a daily alert.

## `onlyOpen` (type: `boolean`):

Skip tenders whose bid deadline has already passed.

## `minDaysToDeadline` (type: `integer`):

Skip tenders that close too soon for you to prepare a bid.

## `minEstimatedValue` (type: `integer`):

In the notice's currency (almost always EUR). Tenders without a published value are skipped when this is set.

## `competitionNoticesOnly` (type: `boolean`):

Keep only calls for bids. Turn off to also get award results and prior information notices.

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

Maximum number of tenders to return, highest relevance first.

## `companyProfile` (type: `string`):

What you sell, where you can deliver, team size, certifications, languages. The AI compares every tender against this.

## `aiFitAnalysis` (type: `boolean`):

For each tender: fit score 0-100, plain-language summary, why it fits, risks and barriers, key requirements, submission language. Charged per analysed tender.

## `outputLanguage` (type: `string`):

Language for the AI summary and notes, e.g. English, German, French.

## Actor input object example

```json
{
  "keywords": [
    "cybersecurity",
    "information security",
    "IT security",
    "penetration testing"
  ],
  "requireKeywordMatch": true,
  "publishedWithinDays": 14,
  "onlyOpen": true,
  "minDaysToDeadline": 0,
  "competitionNoticesOnly": true,
  "maxResults": 50,
  "aiFitAnalysis": false,
  "outputLanguage": "English"
}
```

# Actor output Schema

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

Open EU tenders ranked by relevance, with the AI fit analysis when enabled.

# 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": [
        "cybersecurity",
        "information security",
        "IT security",
        "penetration testing"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("vast_grouse/eu-tender-matcher").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": [
        "cybersecurity",
        "information security",
        "IT security",
        "penetration testing",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("vast_grouse/eu-tender-matcher").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 '{
  "keywords": [
    "cybersecurity",
    "information security",
    "IT security",
    "penetration testing"
  ]
}' |
apify call vast_grouse/eu-tender-matcher --silent --output-dataset

```

## MCP server setup

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

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/aMpCg3floheNapTBc/builds/OHO3pEmhf6qdQhJYB/openapi.json
