# Public Tenders Monitor – EU TED & UK Tenders, Keyword Alerts (`pharaoh_data/public-tenders-monitor`) Actor

Find and monitor public tenders from EU TED, UK Find a Tender, and UK Contracts Finder in one feed. Filter by keyword, CPV code, country, value, and deadline, and get only new and updated notices on each scheduled run.

- **URL**: https://apify.com/pharaoh_data/public-tenders-monitor.md
- **Developed by:** [Pharaoh Data](https://apify.com/pharaoh_data) (community)
- **Categories:** Lead generation, Automation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 tender notices

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

## Public Tenders Monitor – EU TED & UK Tenders, Keyword Alerts

### Every new public tender that fits your business, from the EU and the UK, in one feed

Public buyers publish about 9,500 open tenders a week on TED alone (week of 11 October 2026). This Actor searches the official sources for you: **EU TED** (Tenders Electronic Daily, which covers all 27 EU countries plus the EEA and beyond), **UK Find a Tender**, and **UK Contracts Finder**. It returns the notices that match your keywords, CPV codes, countries, and minimum value, in one clean schema.

Schedule it daily with **Changes only** output and you get just the **new and updated** notices each morning, ready for email, Slack, a CRM, or a bid-tracking sheet.

**Built for:**

- **Companies that sell to the public sector**: IT, consulting, construction, facilities, healthcare suppliers, and SMEs looking for their first public contract.
- **Bid writers and tender consultants** tracking opportunities for several clients.
- **Market and competitive intelligence**: contract awards show who won, for how much, and from which buyer.
- **Tender newsletters and portals** that need a reliable, multi-country feed.

### What you get

|                                        |                                                                                                                                                                                       |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Three official sources, one schema** | TED, Find a Tender, and Contracts Finder notices share the same fields: title, buyer, country, CPV codes, deadline, estimated or awarded value, winners, notice link, documents link. |
| **Search in every EU language**        | Keywords are searched on TED itself, across all its languages and translated titles, so "software" also finds German, French, or Polish notices.                                      |
| **CPV and country filters**            | Use CPV prefixes such as `72` (IT services) or `48` (software), and buyer countries such as `DE`, `France`, or `GB`.                                                                  |
| **Open tenders, planning, awards**     | Calls for bids, prior information and market engagement notices, or contract awards with winners and values.                                                                          |
| **Alerts without duplicates**          | Each notice is labelled new, updated (deadline, value, status, or award changed), or unchanged against the previous run. "Changes only" mode saves just the changes.                  |
| **Official APIs only**                 | TED's public search API and the UK services' open OCDS data, with no scraping of web pages and no logins. The rate limits of each service are respected.                              |

### Quick start

```json
{
    "keywords": ["software", "cloud", "cyber security"],
    "cpvCodes": ["72", "48"],
    "countries": ["DE", "FR", "NL", "GB"],
    "noticeTypes": ["tender"],
    "publishedWithinDays": 3,
    "onlyOpen": true,
    "minValue": 0,
    "trackChanges": true,
    "outputMode": "changes"
}
```

- **Keywords** match when any of them appears. **CPV codes** match when any of a notice's codes starts with one of them. If you use both, a notice must match both.
- **Buyer countries**: the UK sources are searched only when the list is empty or includes `GB`.
- For a daily alert, save the input as a task, schedule it each morning, and set **Output** to **Changes only**. A window of 2–3 days covers late publications, and change tracking removes notices you already received.

### Output

```json
{
    "noticeId": "uk-fts:ocds-h6vhtk-0788ee",
    "source": "uk-fts",
    "noticeType": "tender",
    "title": "Tyres, Tubes and Associated Services",
    "description": "This framework is for the supply and fit of tyres, and a range of ancillary services to East Riding of …",
    "buyer": "East Riding of Yorkshire Council",
    "buyerCountry": "GB",
    "buyerCountryName": "United Kingdom",
    "cpvCodes": ["34350000", "34351000", "34351100", "34352000", "34352100"],
    "procedure": "Open procedure",
    "status": "active",
    "publishedAt": "2026-10-15T16:03:39.000Z",
    "deadline": "2026-11-10T12:00:00.000Z",
    "estimatedValue": 1000000,
    "awardedValue": null,
    "currency": "GBP",
    "winners": [],
    "url": "https://www.find-tender.service.gov.uk/Notice/097662-2026",
    "documentsUrl": "",
    "scrapedAt": "2026-10-18T09:00:00.000Z",
    "changeType": "new",
    "changedFields": [],
    "firstSeenAt": "2026-10-18T09:00:00.000Z",
    "lastSeenAt": "2026-10-18T09:00:00.000Z",
    "closedAt": null
}
```

`RUN_SUMMARY` in the default key-value store shows, for each source, its status and any error, notices read, matching, saved, new, and updated.

### Use it from code, n8n, Make, or an AI agent

```bash
curl -X POST "https://api.apify.com/v2/acts/pharaoh_data~public-tenders-monitor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords":["data analytics"],"countries":["IE","GB"],"publishedWithinDays":7}'
```

```python
import os

from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("pharaoh_data/public-tenders-monitor").call(run_input={
    "cpvCodes": ["45"],
    "countries": ["DE", "AT"],
    "minValue": 1000000,
    "outputMode": "changes",
})
for notice in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(notice["deadline"], notice["buyer"], notice["title"], notice["url"])
```

- **Alerts:** schedule a task, then add a webhook or the Slack, email, or Google Sheets integration on "Run succeeded".
- **AI agents (MCP):** `https://mcp.apify.com/?actors=pharaoh_data/public-tenders-monitor`

### Limits and good to know

- **Sources:** EU TED, UK Find a Tender, and UK Contracts Finder. National portals that don't republish to TED (many below-threshold tenders in EU countries) aren't covered.
- **TED descriptions are in the buyer's language.** Titles use the buyer's own wording; TED's English notice title is used when no procedure title is published.
- **Values** are published only by some buyers, and always in the notice's own currency; `minValue` compares in that currency and skips notices without a value.
- **Find a Tender allows about 12 requests per minute.** The Actor spaces its requests and waits when asked to slow down, so a week of UK notices takes a few minutes.
- **Contracts Finder** returns at most 100 notices per search; the Actor splits the window into smaller searches automatically.
- TED data is © European Union and reusable with attribution. UK data is published under the Open Government Licence. Check each notice on its official page before bidding.

### Pricing

Pay per event: you pay per **saved notice**, plus Apify's small Actor start event. Notices that don't match your filters are free. See the **Pricing** tab for current amounts.

### FAQ

**How do I find CPV codes for my business?**
Use the official CPV list (for example, `72000000` IT services, `48000000` software packages, `45000000` construction, `79000000` business services). Shorter prefixes match whole groups: `72` covers all IT services.

**Why didn't a notice appear?**
Check that its type is selected (open tender, planning, or award), that its deadline hasn't passed (or turn off **Only tenders still open**), and that it was published within the window.

**Does it cover the Gulf?**
Not yet. GCC procurement portals (such as Etimad) are not included, because their access terms do not clearly allow automated reuse.

# Actor input Schema

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

Words or phrases to find in the notice. A notice matches if it contains any of them. TED searches all its languages, so English keywords also find notices written in other languages.

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

Common Procurement Vocabulary codes or prefixes, such as 72000000 (IT services) or 48 (software packages). A notice matches if any of its codes starts with one of them.

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

Keep notices from buyers in these countries (names or ISO codes, such as DE, France, GB). Leave empty for all. UK sources are searched only when the list is empty or includes GB.

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

Open tenders (calls for bids), planning notices (prior information and market engagement), or contract awards (winners and values).

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

Where to search. Leave empty for all three.

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

How far back to look. For a daily scheduled monitor, 2–3 days is enough; change tracking removes notices you already received.

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

Skip open-tender notices whose deadline has passed or that were cancelled.

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

Keep only notices with an estimated or awarded value of at least this amount, in the notice's own currency. 0 keeps all notices, including those without a value.

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

Maximum notices saved per run. Each saved notice is one billable result.

## `includeDescriptions` (type: `boolean`):

Include the procurement description (TED descriptions are in the buyer's language).

## `trackChanges` (type: `boolean`):

Label notices new, updated (deadline, value, status, or award changed), or unchanged compared with the previous run of the same monitor. History is kept in your account's named key-value store public-tenders-monitor-state.

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

"All matching notices" saves every match. "Changes only" saves new and updated notices, for alerts.

## `monitorId` (type: `string`):

Optional name for this monitor's history. When empty, it is derived from the filters.

## Actor input object example

```json
{
  "keywords": [
    "software",
    "cloud"
  ],
  "cpvCodes": [],
  "countries": [],
  "noticeTypes": [
    "tender"
  ],
  "sources": [],
  "publishedWithinDays": 2,
  "onlyOpen": true,
  "minValue": 0,
  "maxResults": 100,
  "includeDescriptions": true,
  "trackChanges": true,
  "outputMode": "all",
  "monitorId": ""
}
```

# Actor output Schema

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

Dataset of tender notices with change status.

## `runSummary` (type: `string`):

Per-source status, notices read, matching, saved, new, and updated.

# 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": [
        "software",
        "cloud"
    ],
    "publishedWithinDays": 2,
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("pharaoh_data/public-tenders-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 = {
    "keywords": [
        "software",
        "cloud",
    ],
    "publishedWithinDays": 2,
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("pharaoh_data/public-tenders-monitor").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": [
    "software",
    "cloud"
  ],
  "publishedWithinDays": 2,
  "maxResults": 100
}' |
apify call pharaoh_data/public-tenders-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pharaoh_data/public-tenders-monitor"
        }
    }
}
```

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/iiRcjUpOWED9ZRHNK/builds/APSm2j31T7AygIOUy/openapi.json
