# Public Tender Monitor — EU TED + French BOAMP (`dalbian/public-tender-monitor`) Actor

Daily digest of open public-procurement notices from TED and BOAMP, filtered by CPV code, keyword, country, department and procedure. Includes the French MAPA contracts below 90 k€ that never reach the European journal.

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

## Pricing

Pay per event

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 Tender Monitor — EU TED + French BOAMP

A daily digest of open public-procurement notices from **TED**, the European Union's official Tenders Electronic Daily, and **BOAMP**, the French official bulletin — filtered by CPV code, keyword, country, department and procedure, in one run.

Set `publishedWithinDays` to 1, schedule it each morning, and you get exactly what appeared since yesterday. Nothing repeated, nothing missed.

### Why both sources

TED covers every EU member state, but only above the European thresholds. BOAMP carries those same notices *and* the **MAPA** procedures below 90 000 € — the contracts a small or mid-sized firm can realistically win, and which never appear in the European journal at all.

A search on construction work across Vaucluse, Bouches-du-Rhône and Gard over one week returns notices from both: a European-threshold accord-cadre from Nîmes Métropole alongside a sub-90 k€ quay repair at the La Ciotat shipyards. Watch TED alone and you see only half the market — the half you are least likely to win.

### What comes back

One summary row per run, then one row per notice:

| Field | Example |
| --- | --- |
| `source` | TED or BOAMP |
| `title` | Travaux de construction d'une caserne de gendarmerie et de 27 logements |
| `buyer` | Mairie de Venelles · Métropole de Lyon · Syndicat des Eaux Durance-Ventoux |
| `deadline` | 2026-10-16T10:00 |
| `cpvCodes` | 45243510, 45111240 |
| `departments` / `placeOfPerformance` | 13, 84, 83 |
| `procedure`, `family` | Procédure adaptée · Marchés <90 k€ (MAPA) |
| `noticeUrl` | Direct link to the full notice |

Notices are sorted newest first and deduplicated per source.

### Filtering that matches how firms actually work

**CPV codes** are the EU's universal classification of what is being bought, and a truncated code matches its whole branch: `45000000` covers all construction, `72000000` all IT services, `45330000` just plumbing. This is the precise filter.

**Departments** are usually the decisive one for a French firm — most will not travel three regions for a 60 k€ job.

**Keywords** search the notice object, in the language of the notice. `toiture` finds French notices; `roofing` will not.

**Notice families** let you keep only MAPA, which is the single most useful setting for a small contractor.

### Built for scheduling

This Actor is designed to be run on a schedule rather than by hand. The default window of one day makes each run a clean delta. On a quiet day or a weekend it will legitimately return nothing, and says so in the summary row rather than looking broken.

For a first look at a market you have never watched, set the window to 30 days, see the shape of it, then drop back to 1.

### Who uses this

Construction, public-works, engineering and IT firms that bid for public contracts and cannot afford to miss a deadline. Bid-writing consultancies watching several clients' sectors at once. Trade federations and chambers of commerce tracking regional activity. Analysts and journalists following public spending. Anyone currently paying a commercial *veille* service for what is, by law, free public information.

### Sources and licence

**TED** — the EU Publications Office's official procurement journal, via its public search API. **BOAMP** — the French Direction de l'information légale et administrative, via the public Opendatasoft catalogue, 1.7 million notices deep.

Access to public-procurement notices is free and anonymous by law, and reuse is covered by the Licence Ouverte. No credentials, no personal data, no scraping of a private database.

### Frequently asked

**Why did today's run return nothing?**
Because nothing matching was published. Public buyers publish on working days, so a Sunday run with a one-day window is usually empty. The summary row tells you the window it looked at.

**Does it include contract awards, not just calls for tender?**
Both are published and both come back. Filter on the notice nature if you only want live opportunities, or leave `onlyOpenTenders` on, which keeps only notices whose deadline has not passed.

**Can I get the tender documents themselves?**
The notice URL takes you to the full record and its downloadable file on the official site. The documents stay where they are published.

**Why are some notices in English and some in French?**
TED translates titles into all official languages and this Actor takes the English one where available. BOAMP publishes in French only. The buyer, deadline and CPV fields are language-independent.

# Actor input Schema

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

TED is the EU's official journal of public contracts, covering every member state above the European thresholds. BOAMP is the French bulletin and, crucially, also carries the MAPA notices below 90 k€ that never reach TED. Use both to see a French market whole.

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

Only notices published in the last N days. Leave at 1 and schedule this Actor every morning to get a clean daily digest with nothing repeated. Raise it to 7 or 30 for a first sweep of a market you have never looked at.

## `onlyOpenTenders` (type: `boolean`):

Drop notices whose submission deadline has already passed. Turn this off when you are studying a market's history rather than looking for work to bid on.

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

Common Procurement Vocabulary codes, one per line — the EU's universal classification of what is being bought. A truncated code matches its whole branch, so 45000000 covers all construction work and 72000000 all IT services. Applies to TED.

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

Words to look for in the notice title or object, one per line. Use the language of the notice — 'toiture' will find French notices, 'roofing' will not. Several keywords are combined with OR.

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

Three-letter country codes for the place of performance, such as FRA, BEL, DEU, ESP, ITA. Leave empty for the whole EU.

## `departments` (type: `array`):

French department codes, one per line, such as 84, 13, 2A or 974. Leave empty for the whole country. This is usually the single most useful filter for a firm that only travels so far.

## `boampFamilies` (type: `array`):

MAPA covers the adapted procedures below 90 k€ — the contracts small firms actually win, and the reason to watch BOAMP rather than TED alone. JOUE mirrors the European notices. Leave empty for all.

## `maxNoticesPerSource` (type: `integer`):

Cap per source. A daily run with sensible filters rarely returns more than a few dozen, so this mainly protects a first broad sweep from running away.

## Actor input object example

```json
{
  "sources": [
    "TED",
    "BOAMP"
  ],
  "publishedWithinDays": 1,
  "onlyOpenTenders": true,
  "cpvCodes": [
    "45000000"
  ],
  "boampFamilies": [],
  "maxNoticesPerSource": 200
}
```

# Actor output Schema

# 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 = {
    "cpvCodes": [
        "45000000"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("dalbian/public-tender-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 = { "cpvCodes": ["45000000"] }

# Run the Actor and wait for it to finish
run = client.actor("dalbian/public-tender-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 '{
  "cpvCodes": [
    "45000000"
  ]
}' |
apify call dalbian/public-tender-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dalbian/public-tender-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/5dAPZO6cmuZ9oozri/builds/qd6jWo4JSeKofzVwI/openapi.json
