# Public Tenders Monitor: TED (EU) + BOAMP (France) (`frenchdatalab/eu-france-public-tenders`) Actor

Search and monitor public tenders from all EU countries (TED) and every French notice incl. small ones (BOAMP): keywords, CPV, countries, French departments, open calls, awards with winners and amounts. Daily alert mode returns only new notices.

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

## Pricing

from $4.00 / 1,000 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: TED (EU) + BOAMP (France)

**Never miss a public contract again.** Search and monitor public tenders from **all EU countries** (TED, the EU Official Journal) and **every French notice — including the many smaller national ones that never reach TED** (BOAMP), in one clean, deduplicated table.

Schedule it daily in **alert mode** and receive **only the notices you have not seen yet**, straight to Google Sheets, Slack, email, Make, Zapier or your CRM.

### What can you do with it?

- 🔔 **Daily tender alerts.** *"Every new IT call for tenders in Germany, Austria and France"*, *"every cleaning contract in the Rhône department"* — only new notices on each run.
- 🏆 **Competitive intelligence.** Award notices tell you **who won, and for how much**: track your competitors, find partners, benchmark prices.
- 📈 **Business development.** Filter on minimum value to focus on contracts worth answering, or on prior information notices to prepare before the call is published.
- 📊 **Market analysis.** Pull months of history (tens of thousands of notices) to study buyers, budgets and winners in your sector.

### Why this Actor?

| | This Actor | Typical tender scrapers |
|---|---|---|
| EU (TED) **and** French national notices (BOAMP) | ✅ one run, one format | ❌ one source |
| Small French contracts below EU thresholds | ✅ | ❌ (TED only) |
| Alert mode: only notices not sent before | ✅ `monitorName` | ❌ you deduplicate yourself |
| Winners & awarded amounts | ✅ | Rare |
| Duplicates (same procedure on both sources, corrigenda) | ✅ merged | ❌ |
| Placeholder amounts (0 / 1 €) cleaned | ✅ | ❌ |
| History beyond 10,000 results | ✅ automatic splitting | ❌ |
| Official open data, legal reuse | ✅ | varies |

### Input

| Field | Description | Example |
|---|---|---|
| `keywords` | Full-text words, any language; a notice matches if it contains at least one | `["logiciel", "software"]` |
| `cpvCodes` | CPV categories (sub-categories included) | `["72000000"]` |
| `noticeTypes` | `contract` (calls for tenders), `award` (winners), `prior` (prior information) | `["contract"]` |
| `countries` | Buyer countries (ISO3). Empty = all | `["FRA", "DEU", "AUT"]` |
| `frenchDepartments` | French buyer departments | `["69", "75"]` |
| `publishedWithinDays` | 1 = daily alert, 7 = weekly… | `1` |
| `publishedFrom` / `publishedTo` | Date range for history | `"2026-01-01"` |
| `openOnly` | Calls whose deadline has not passed (default `true`) | `true` |
| `minEstimatedValue` / `keepUnknownValue` | Minimum value in €, and whether to keep notices without a published value | `500000` / `true` |
| `monitorName` | **Alert mode**: returns only notices not returned before under this name | `"it-dach-fr"` |
| `language` | Language of EU notices (fallback: original language) | `"en"` |
| `sources` | `ted`, `boamp` | both |
| `maxResults` | Maximum notices per run | `500` |

#### Recipes

```json
{ "keywords": ["software", "logiciel", "Software"], "countries": ["FRA", "DEU", "AUT"], "publishedWithinDays": 1, "monitorName": "it-alert" }
```

```json
{ "keywords": ["nettoyage"], "countries": ["FRA"], "frenchDepartments": ["69"], "publishedWithinDays": 30 }
```

```json
{ "cpvCodes": ["72000000"], "countries": ["DEU"], "noticeTypes": ["award"], "publishedWithinDays": 30 }
```

**Daily alert:** save your input as a Task, add a Schedule (e.g. every morning at 7:00) with `publishedWithinDays: 2` and a `monitorName`, and connect an integration. Each run only delivers new notices.

### Output

Real examples:

```json
{
    "id": "boamp:26-...",
    "source": "boamp",
    "title": "Nettoyage de la Gare Routière Internationale provisoire de Gerland - Lyon 7ème et des nouvelles poches de stationnement...",
    "buyerName": "Société Publique Lyonnaise de Mobilités",
    "country": "FRA",
    "frenchDepartments": ["69"],
    "cpvCodes": ["90910000"],
    "noticeType": "contract",
    "procedureType": "Procédure Ouverte",
    "contractType": "services",
    "publicationDate": "2026-09-27",
    "deadline": "2026-10-26T11:00:00",
    "estimatedValue": null,
    "scope": "National (France)",
    "url": "https://www.boamp.fr/pages/avis/?q=idweb:26-..."
}
```

```json
{
    "id": "ted:635932-2026",
    "source": "ted",
    "title": "Germany – Multimedia software development services – M2_VE08_Medienguide",
    "buyerName": "Stadt Forst (Lausitz), Die Bürgermeisterin, Fachbereich Bauverwaltung",
    "country": "DEU",
    "cpvCodes": ["72212520", "72212100"],
    "noticeType": "award",
    "publicationDate": "2026-09-16",
    "winners": ["ö_konzept Agentur für Werbung und Kommunikation GmbH & Co. KG"],
    "url": "https://ted.europa.eu/en/notice/-/detail/635932-2026",
    "pdfUrl": "https://ted.europa.eu/en/notice/635932-2026/pdf"
}
```

Other fields: `description` (EU notices), `buyerCity`, `estimatedValue`, `awardedValue`, `currency`, `procedureId` (official procedure identifier shared by TED and BOAMP), `categories` (BOAMP descriptors), `noticeTypeCode`, `sourceAttribution`. A `SUMMARY` record counts notices by source, country and type.

### Sources & licence

- **TED** — Publications Office of the European Union. Reuse for commercial and non-commercial purposes with source acknowledgement (Commission Decision 2011/833/EU).
- **BOAMP** — Direction de l'information légale et administrative (DILA), *Licence Ouverte 2.0*.

Each item carries its `sourceAttribution`.

### Pricing

Pay per notice returned. In alert mode you only pay for new notices. Set a maximum cost per run and the Actor stops exactly there.

### FAQ

**Why do some notices have no value?** Many buyers do not publish an estimate. Amounts of 0 or 1 € (used to hide the price) are treated as unknown.

**How fast is it?** French notices: thousands per minute. EU notices: the official TED API asks clients to go slowly, so large EU extractions take a few minutes (≈250 notices every 5 seconds).

**Why are French notices from BOAMP rather than TED?** BOAMP publishes every French notice, including national ones below EU thresholds, and the EU-level ones too — so French results are complete and not duplicated.

**Something is wrong?** Open an issue with your run link — it will be fixed quickly.

***

#### 🇫🇷 En bref

Veille des **appels d'offres publics** : **tous les pays européens** (TED) et **toute la France, y compris les petits marchés nationaux** (BOAMP). Mots-clés, codes CPV, pays, départements, avis de marché ouverts, **résultats avec attributaires et montants**, **mode alerte** qui ne renvoie que les nouveaux avis à chaque exécution programmée. Export Excel, CSV, Google Sheets, Slack, e-mail.

# Actor input Schema

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

Words searched in the full text of the notices, in any language ("software", "logiciel", "nettoyage", "cleaning"). A notice matches if it contains at least one of them. Leave empty to get every notice.

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

Official procurement categories, sub-categories included (e.g. 72000000 = IT services, 45000000 = construction works, 90910000 = cleaning).

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

Calls for tenders (to answer), award notices (who won, for how much) and prior information notices (upcoming tenders).

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

Buyer countries. Empty = all European countries publishing on TED plus France.

## `frenchDepartments` (type: `array`):

For France: department numbers of the buyer (e.g. "75", "69", "13", "2A"). Only applies to French notices.

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

1 for a daily alert, 7 for a weekly one. Ignored when 'Published from' is set.

## `publishedFrom` (type: `string`):

Optional start date (YYYY-MM-DD) for historical searches.

## `publishedTo` (type: `string`):

Optional end date (YYYY-MM-DD). Default: today.

## `openOnly` (type: `boolean`):

For calls for tenders: keep only those whose submission deadline has not passed.

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

Minimum estimated (or awarded) value. Many notices do not publish a value: see the next option.

## `keepUnknownValue` (type: `boolean`):

When a minimum value is set, also keep notices that do not publish any value (recommended).

## `monitorName` (type: `string`):

Give your watch a name (e.g. "it-lyon") and schedule the Actor daily: each run returns ONLY notices not sent in previous runs with the same name. Leave empty for a normal search.

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

Preferred language for TED titles, buyers and descriptions (falls back to the original language). French notices stay in French.

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

TED = EU Official Journal (all EU countries, above EU thresholds). BOAMP = every French notice, including smaller national ones.

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

Maximum number of notices returned by the run.

## Actor input object example

```json
{
  "keywords": [
    "logiciel",
    "software"
  ],
  "noticeTypes": [
    "contract"
  ],
  "publishedWithinDays": 7,
  "openOnly": true,
  "keepUnknownValue": true,
  "language": "en",
  "sources": [
    "ted",
    "boamp"
  ],
  "maxResults": 50
}
```

# Actor output Schema

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

No description

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

No description

# 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": [
        "logiciel",
        "software"
    ],
    "publishedWithinDays": 7,
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("frenchdatalab/eu-france-public-tenders").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": [
        "logiciel",
        "software",
    ],
    "publishedWithinDays": 7,
    "maxResults": 50,
}

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

```

## MCP server setup

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

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/cLut4MkfOxrxuKDwi/builds/1w1D5SZtIgwebNCcJ/openapi.json
