# Govt Tender Monitoring (`musa_vertex_studio/govt-tender-monitoring`) Actor

Discover, filter, and monitor European government tenders using the official EU TED API. Search procurement opportunities by keywords, countries, CPV codes, and deadlines. Includes IT tender relevance scoring, change detection, and structured JSON/CSV exports.

- **URL**: https://apify.com/musa_vertex_studio/govt-tender-monitoring.md
- **Developed by:** [M usman Shafique](https://apify.com/musa_vertex_studio) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.003 / actor start

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

## Government Tender Monitor — EU Public Procurement Intelligence

[![Apify Actor](https://img.shields.io/badge/Apify-Actor-blue?logo=apify)](https://apify.com)
[![Python 3.12](https://img.shields.io/badge/python-3.12-blue.svg)](https://www.python.org/downloads/release/python-3120/)
[![Official TED API](https://img.shields.io/badge/data_source-EU_TED_API_v3-green)](https://ted.europa.eu)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

**Government Tender Monitor** is a reliable, automated cloud solution for discovering, qualifying, and monitoring European public procurement notices directly from the official **TED (Tenders Electronic Daily) Search API v3**.

Whether you are tracking IT contracts, civil construction tenders, healthcare procurement, or engineering projects, this Actor continuously identifies relevant contract notices across European public authorities, calculates explainable match scores, and alerts you to newly published or updated opportunities.

***

### 🎯 Who Should Use This Actor?

- **Government Contractors & Bid Teams:** Automate daily RFP/RFQ tracking across EU public buyers without tedious manual portal checks.
- **IT & Software Consultancies:** Pinpoint software development, cloud migration, cybersecurity, and system integration contracts.
- **Construction & Engineering Firms:** Track infrastructure, civil engineering, building renovation, and architectural framework tenders.
- **Medical & Healthcare Suppliers:** Monitor hospital equipment, pharmaceuticals, and clinical diagnostic tenders.
- **Sales Intelligence & Market Researchers:** Analyze public sector spending, buyer behavior, and procurement pipelines across Europe.

***

### 🌐 Supported Coverage & Country Formats

The Actor connects directly to the official EU TED database covering all contracting authorities subject to European procurement directives:

- **27 EU Member States:** Austria (`AUT`), Belgium (`BEL`), Bulgaria (`BGR`), Croatia (`HRV`), Cyprus (`CYP`), Czechia (`CZE`), Denmark (`DNK`), Estonia (`EST`), Finland (`FIN`), France (`FRA`), Germany (`DEU`), Greece (`GRC`), Hungary (`HUN`), Ireland (`IRL`), Italy (`ITA`), Latvia (`LVA`), Lithuania (`LTU`), Luxembourg (`LUX`), Malta (`MLT`), Netherlands (`NLD`), Poland (`POL`), Portugal (`PRT`), Romania (`ROU`), Slovakia (`SVK`), Slovenia (`SVN`), Spain (`ESP`), Sweden (`SWE`).
- **EEA / EFTA & Partner States:** Iceland (`ISL`), Liechtenstein (`LIE`), Norway (`NOR`), Switzerland (`CHE`), United Kingdom (`GBR`), Ukraine (`UKR`), and EU institutions.
- **Input Flexibility:** You can specify countries either as **3-letter ISO alpha-3 codes** (e.g. `DEU`, `FRA`, `ESP`) or as standard **English country names** (e.g. `Germany`, `France`, `Spain`). Leaving the `countries` field empty searches across all European procurement entities.

***

### 🔍 Key Search & Filtering Capabilities

#### 1. Keywords & Boolean Match Modes

- **`keywords`**: Enter arbitrary keywords relevant to your industry (e.g., `["cloud", "cybersecurity"]` or `["concrete", "bridge repair"]`).
- **`keywordMatchMode`**:
  - `any` (OR logic, default): Matches notices containing at least one of your specified keywords.
  - `all` (AND logic): Requires all specified keywords to be present in the notice.
- **`keywordSearchScope`**:
  - `title_and_description` (Recommended): Searches notice titles and work descriptions.
  - `title`: Matches only within the official tender title.
  - `full_text`: Queries the broader full notice dossier.
- **Context-Aware Negation Handling:** The relevance engine understands negative qualification phrases (e.g., *"Installation services (except software)"*, *"sans logiciel"*, *"ohne Software"*). Negative exclusion clauses are not treated as affirmative evidence for that keyword, preventing false-positive alerts while preserving genuine contracts that contain incidental exclusions.

#### 2. Multi-Sector CPV Filtering

Common Procurement Vocabulary (CPV) codes provide standardized classification across all sectors. CPV filtering is completely optional and customizable:

- **IT & Digital:** `72000000` (IT services), `48000000` (Software package), `30200000` (Computer equipment)
- **Construction & Infrastructure:** `45000000` (Construction work), `71000000` (Architectural and engineering)
- **Healthcare & Medical:** `85000000` (Health and social work), `33100000` (Medical equipments)
- **Transport & Logistics:** `60000000` (Transport services)
- **Education & Training:** `80000000` (Education and training services)

#### 3. Relevance Scoring Profiles

- **`general` (Default):** Evaluates notices neutrally across any sector without industry bias. Perfect for construction, healthcare, transport, or multi-disciplinary tenders.
- **`it`:** Tailored for software and digital services. Prioritizes Division 72, 48, and 302 CPVs and matches against tech capabilities.
- **`none`:** Disables relevance weighting. All notices matching search criteria receive full qualification score.

#### 4. Search Scopes & Deadline Filtering

- **`searchScope`**:
  - `active` (Default): Currently open tenders available for bidding.
  - `recent`: Recently published notices.
  - `all`: Full TED historical archive.
- **`onlyOpen`**: When `true`, filters out notices whose deadline has already elapsed.
- **`includeUnknownDeadlines`**: European authorities frequently omit submission deadlines in early Prior Information Notices (PIN) or design contests. Set to `true` if you wish to see early-stage notices that do not yet specify a final cutoff timestamp.
- **`sortOrder`**: `desc` (newest publication date first, recommended) or `asc` (oldest first).

#### 5. Smart Delivery & Paging Limits

- **`maxItems`**: The target maximum number of eligible, qualified records to deliver into the output dataset.
- **`maxNoticesScanned`**: Safety cap on upstream TED notices scanned across pagination pages (default: 250). When deduplication or strict filters suppress older or irrelevant notices, the Actor continues fetching additional TED pages until `maxItems` is satisfied or `maxNoticesScanned` is reached.

***

### 🔄 Persistent Monitoring & Watchlist Behavior

When `monitoringEnabled: true`, the Actor acts as a continuous watchdog across recurring runs:

- **"NEW to Watchlist" vs. "Newly Published":**
  - **NEW to Watchlist:** The tender was newly identified and delivered by your monitoring task (it was not present in your persistent state from previous runs).
  - **Newly Published:** The tender was published on TED recently according to its `publicationDate`. A notice can be "NEW" to your watchlist even if published several days ago if this is the first time your monitor evaluated it.
- **`onlyNew: true`:** Suppresses notices that were previously delivered and have not changed.
- **`includeUpdated: true`:** Flags and redelivers existing notices if their submission deadline, estimated value, or contract terms have been officially amended.
- **`stateName`:** Assign unique state names (e.g. `it-tenders-watchlist` vs `construction-germany`) to maintain independent monitoring pipelines under the same Apify account.

***

### 📥 Example Configurations

#### Example 1: IT & Cloud Procurement Watchlist

```json
{
  "keywords": ["software", "cloud migration", "cybersecurity"],
  "keywordMatchMode": "any",
  "keywordSearchScope": "title_and_description",
  "strictRelevanceFilter": true,
  "countries": ["DEU", "FRA", "NLD"],
  "cpvCodes": ["72000000", "72200000"],
  "scoringProfile": "it",
  "searchScope": "active",
  "onlyOpen": true,
  "includeUnknownDeadlines": false,
  "maxItems": 25,
  "maxNoticesScanned": 250,
  "minimumDaysRemaining": 7,
  "minimumRelevanceScore": 40,
  "monitoringEnabled": true,
  "onlyNew": true,
  "includeUpdated": true,
  "stateName": "it-procurement-watch"
}
```

#### Example 2: Construction & Civil Engineering Search

```json
{
  "keywords": ["bridge construction", "road rehabilitation", "concrete"],
  "keywordMatchMode": "any",
  "keywordSearchScope": "title_and_description",
  "countries": ["AUT", "DEU", "CHE"],
  "cpvCodes": ["45000000", "45220000", "71300000"],
  "scoringProfile": "general",
  "searchScope": "active",
  "onlyOpen": true,
  "includeUnknownDeadlines": true,
  "maxItems": 50,
  "maxNoticesScanned": 300,
  "monitoringEnabled": false
}
```

***

### 📤 Output Dataset Format

Every record delivered to the dataset includes rich qualification data, transparent scoring rationale, and field-level warnings:

```json
{
  "noticeId": "123456-2024",
  "noticeVersion": "1",
  "title": "Framework agreement for cloud infrastructure and managed services",
  "description": "Provision of enterprise cloud migration, DevOps engineering, and infrastructure monitoring.",
  "buyerName": "Federal Office for Information Security (BSI)",
  "buyerCountry": "DEU",
  "buyerCity": "Bonn",
  "cpvCodes": ["72000000", "72222300"],
  "noticeType": "cn-standard",
  "publicationDate": "2024-03-15+01:00",
  "submissionDeadline": "2024-04-30T12:00:00+02:00",
  "daysRemaining": 46,
  "estimatedValue": 1250000.0,
  "currency": "EUR",
  "sourceUrl": "https://ted.europa.eu/en/notice/-/detail/123456-2024",
  "source": "TED - Publications Office of the European Union",
  "language": "en",
  "relevanceScore": 92,
  "matchReasons": [
    "Matched target CPV code: 72000000 (IT services: consulting, software development, Internet and support).",
    "Found search keywords: cloud, software.",
    "Contracting authority located in target country: DEU.",
    "Generous submission timeline remaining (46 days) for bid preparation."
  ],
  "warnings": [],
  "qualificationWarnings": [],
  "monitoringStatus": "NEW",
  "lastCheckedAt": "2026-10-24T02:00:00+00:00"
}
```

#### Null-Value Guarantees

- European procurement regulations permit contracting authorities to withhold estimated budgets to prevent price fixing.
- When an authority does not publish a budget, currency, deadline, or notice type, the corresponding output field is strictly output as `null`.
- The Actor **never fabricates, guesses, or hallucinates** missing financial values or deadlines.

***

### 💡 Scoring Methodology & Warnings

The relevance engine calculates a score from 0 to 100 based on five deterministic pillars:

1. **Classification (30 pts):** Direct alignment with target CPVs.
2. **Keywords & Services (25 pts):** Keyword presence evaluated with affirmative context analysis.
3. **Geography (15 pts):** Proximity to preferred or target countries.
4. **Budget Suitability (15 pts):** Match with minimum/maximum contract boundaries.
5. **Timeline Viability (15 pts):** Days remaining before submission cutoff.

#### Transparent Advisory Warnings (`warnings`)

- **Missing Information:** Advisory notices flag when deadlines or budgets were not disclosed by the buyer.
- **Nominal Placeholders:** Notices publishing nominal values such as `0.01 EUR` or `1.00 EUR` are flagged with a cautionary advisory warning indicating they likely represent administrative placeholders rather than actual contract limits.
- **Negation Advisories:** Tenders containing negated keyword mentions (e.g. *"excluding software"*) include an explicit warning explaining that the keyword was detected within an exclusion clause.

***

### 💰 Pricing & Monetization Model

The Actor utilizes Apify's **Pay-Per-Event (PPE)** consumption model:

- **Pay for Results Only:** You are only billed when a notice matching your search and qualification criteria is delivered to the dataset.
- **No Charge for Excluded Notices:** Irrelevant tenders, historical notices excluded by `onlyOpen`, or duplicate notices suppressed by `onlyNew` incur zero event charges.
- **Zero-Result Runs Are Free:** If a monitoring run finds no new eligible tenders, no event charges are accrued.
- **Idempotency Protection:** Journaled recovery ensures you are never charged twice for the same notice across run retries.

***

### 🛡️ Reliability, Concurrency & Safe Deployment

#### Single-Writer Concurrency Recommendation

Apify Key-Value Stores provide distributed cloud storage but do not expose atomic compare-and-swap (CAS) primitives.

- While the Actor employs a two-phase write-and-verify lease mechanism to prevent concurrent overwrites, **you should configure your Apify Schedule settings with `maxConcurrency: 1`**.
- This ensures that only one Actor instance processes a specific `stateName` watchlist at any given moment, eliminating race hazards and maintaining strict monitoring continuity.

#### Failure Recovery & Journaling

- If a network error occurs during dataset push, the Actor maintains a pending-delivery journal.
- Interrupted runs recover pending deliveries safely on subsequent runs without data loss or duplicate alerts.

***

### ⚖️ Data Source Attribution & Disclaimer

- **Official Source:** Sourced from **Tenders Electronic Daily (TED)**, the official database of European public procurement, operated by the Publications Office of the European Union.
- **Open Data Compliance:** Notices are processed in accordance with European Commission Open Data Decision 2011/833/EU.
- **Important Disclaimer:** Procurement information is presented as reported by the contracting authorities. Notice timeliness, deadlines, budgets, and procedural specifications are subject to official modifications and corrigenda. Always verify the authoritative dossier on the linked `sourceUrl` before committing resources to bid preparation.

***

### 🛠️ Troubleshooting & Support

| Issue | Cause | Solution |
| :--- | :--- | :--- |
| **0 records delivered (Run succeeded)** | `onlyNew: true` suppressed notices previously delivered. | Expected behavior. If testing, run with a new `stateName` or `onlyNew: false`. |
| **Validation Error on Country** | Invalid country code format. | Use 3-letter ISO alpha-3 codes (e.g. `DEU`, `FRA`) or valid English names (e.g. `Germany`). |
| **Few or No Results** | Overly restrictive keywords or CPVs. | Switch `keywordMatchMode` to `any`, broaden keywords, or set `scoringProfile` to `general`. |
| **Old notices returned** | `searchScope` set to `all` or `onlyOpen: false`. | Set `searchScope: "active"` and `onlyOpen: true`. |
| **Missing budget values** | Buyer withheld estimated contract value. | Normal EU procurement practice. Field is returned as `null` with advisory warning. |

For bug reports or feature requests, please submit an issue via the repository.

# Actor input Schema

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

Arbitrary search keywords to match in tender titles and descriptions across any sector (e.g. 'software', 'cloud', 'hospital equipment', 'solar panels', 'road construction', 'consulting'). Leave empty to match all notices.

## `keywordMatchMode` (type: `string`):

Matching logic when multiple keywords are specified: 'any' (OR - matches notices containing at least one keyword) or 'all' (AND - matches notices containing all specified keywords).

## `keywordSearchScope` (type: `string`):

Fields in the TED notice to query for keywords: 'title_and_description' (searches notice titles and descriptions), 'title' (searches notice titles only), or 'full_text' (searches full notice text).

## `strictRelevanceFilter` (type: `boolean`):

When enabled, drops any notice whose title, description, or CPV codes do not directly match user-specified keywords or CPV criteria, eliminating spurious full-text matches.

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

Select one or more countries to search. Displayed with readable names and submitted as ISO alpha-3 codes. Leave empty to search all countries.

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

Common Procurement Vocabulary codes to filter by sector (e.g. 72000000 for IT, 45000000 for Construction, 85000000 for Healthcare, 80000000 for Education, 71000000 for Engineering). Leave empty to search all sectors.

## `searchScope` (type: `string`):

TED database search scope: 'active' (currently open tenders), 'recent' (recently published notices), or 'all' (full historical archive).

## `sortOrder` (type: `string`):

Publication date sort direction: 'desc' (newest first, recommended) or 'asc' (oldest first).

## `scoringProfile` (type: `string`):

Relevance evaluation profile. 'general' assesses qualification neutrally across any procurement sector without IT bias. 'it' applies IT-specific CPV rules. 'none' gives full qualification score to all notices.

## `publicationDateFrom` (type: `string`):

Earliest notice publication date in YYYY-MM-DD format (e.g., 2024-01-01).

## `publicationDateTo` (type: `string`):

Latest notice publication date in YYYY-MM-DD format (e.g., 2026-12-31).

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

If enabled, only notices with future submission deadlines are returned.

## `includeUnknownDeadlines` (type: `boolean`):

When onlyOpen is true, specifies whether notices lacking a known submission deadline should be retained (true) or excluded (false).

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

Maximum number of tender records to return (1 to 1000).

## `maxNoticesScanned` (type: `integer`):

Maximum number of raw notices to scan across pages when filtering for eligible or new tenders (1 to 5000). Prevents excessive API usage when few notices match criteria.

## `language` (type: `string`):

Preferred ISO language code for titles and descriptions (e.g., 'en', 'de', 'fr', 'es'). Default is 'en'.

## `companyServices` (type: `array`):

List of services or capabilities provided by your company (e.g., 'civil engineering', 'medical supplies', 'cloud architecture'). Used to calculate match relevance.

## `preferredCountries` (type: `array`):

Countries where your company actively bids or prefers to deliver services. Displayed with readable names.

## `minimumContractValue` (type: `number`):

Minimum contract value in notice currency (e.g. 50000). Notices with lower specified value will be penalized or filtered.

## `maximumContractValue` (type: `number`):

Maximum contract value in notice currency (e.g. 5000000). Notices exceeding this will be penalized or filtered.

## `minimumDaysRemaining` (type: `integer`):

Minimum days remaining before the submission deadline. Tenders with fewer days are flagged or filtered.

## `minimumRelevanceScore` (type: `integer`):

Filter out notices whose calculated relevance score is below this threshold (0 to 100).

## `monitoringEnabled` (type: `boolean`):

Track notices across scheduled runs using Apify key-value store to identify NEW, UPDATED, and UNCHANGED tenders.

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

When monitoring is enabled, exclude previously delivered unchanged notices.

## `includeUpdated` (type: `boolean`):

When monitoring is enabled, include notices that changed since the last run (e.g. amended deadlines, revised values).

## `stateName` (type: `string`):

Optional custom name for the persistent state store. Useful for running multiple independent search profiles.

## `debug` (type: `boolean`):

Enable verbose logging for debugging and diagnostics.

## Actor input object example

```json
{
  "keywords": [],
  "keywordMatchMode": "any",
  "keywordSearchScope": "title_and_description",
  "strictRelevanceFilter": false,
  "countries": [],
  "cpvCodes": [],
  "searchScope": "active",
  "sortOrder": "desc",
  "scoringProfile": "general",
  "onlyOpen": true,
  "includeUnknownDeadlines": false,
  "maxItems": 50,
  "maxNoticesScanned": 250,
  "language": "en",
  "companyServices": [],
  "preferredCountries": [],
  "minimumDaysRemaining": 7,
  "minimumRelevanceScore": 0,
  "monitoringEnabled": false,
  "onlyNew": false,
  "includeUpdated": true,
  "debug": false
}
```

# Actor output Schema

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

Dataset of qualified and scored European government IT procurement notices from TED.

# 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("musa_vertex_studio/govt-tender-monitoring").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("musa_vertex_studio/govt-tender-monitoring").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 '{}' |
apify call musa_vertex_studio/govt-tender-monitoring --silent --output-dataset

```

## MCP server setup

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

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/V2goknvIFxxLVIk8u/builds/j2o2CRMCthCLdsySn/openapi.json
