# French Public Tenders & Contracts – BOAMP + DECP (`yck69/french-public-procurement`) Actor

French public procurement in one Actor: open tenders from BOAMP with buyer contacts, CPV, estimated value, lots and documents link; awarded contracts from DECP with winners and amounts; market analysis (top winners, buyers, sectors); alerts for new tenders.

- **URL**: https://apify.com/yck69/french-public-procurement.md
- **Developed by:** [yck](https://apify.com/yck69) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.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

## French Public Tenders & Contracts – BOAMP + DECP (Marchés Publics)

Everything about **French public procurement** in one Actor:

- **Tenders**: open calls for tenders and award results from **BOAMP** (~120,000 notices a year), with the details you need to bid: deadline (Paris time), estimated value, CPV sector, lots, **documents link**, and the buyer's **contact name, email and phone**.
- **Awarded contracts**: **who won what, for how much**, from **DECP** (3+ million contracts, updated daily): buyer, winner (SIRET, size, activity, distance), amount, procedure, number of bids.
- **Market analysis**: top winners, top buyers, sectors, departments or monthly trends for any filter, with totals, medians and **market shares**.
- **Alerts**: schedule the Actor and get only the tenders you haven't seen yet.

**From $2 per 1,000 notices.** Free count preview.

### What data can you get?

<table>
<tr><td>📑 Tender title and lots</td><td>⏳ Deadline (Paris time)</td><td>💶 Estimated value</td></tr>
<tr><td>🏷️ CPV sector</td><td>📎 Documents link</td><td>🏛️ Buyer and contact</td></tr>
<tr><td>🏆 Winner (SIRET, size, activity)</td><td>💶 Awarded amount</td><td>🔢 Number of bids</td></tr>
<tr><td>📍 Department and region</td><td>📊 Top winners, buyers, market shares</td><td>🔔 Alerts for new tenders</td></tr>
</table>

### How to use it

1. Click **Try for free** at the top of this page.
2. Choose a mode: **tenders**, **contracts** or **analysis**.
3. Filter by CPV sector, region, department, buyer, winner or dates.
4. Click **Start**, or schedule it for daily tender alerts.
5. Download as JSON, CSV or Excel.

### Why this Actor

| | This Actor | Typical BOAMP scrapers |
|---|---|---|
| Buyer email & phone | ✅ ~80% of notices (EU *and* national formats) | Partial or none |
| Winners of national award notices | ✅ Parsed from the text, lot by lot, with amounts | Raw text only |
| Bids received, unsuccessful procedures | ✅ | ❌ |
| Who won past contracts (DECP) | ✅ 3M+ contracts, same Actor | Separate tool, if any |
| Market analysis (top winners, shares) | ✅ | ❌ |
| New-tender alerts | ✅ Remembers what you've seen | ❌ |
| Deadlines in the right time zone | ✅ | Often off by 1–2 hours |
| Results per search | Unlimited (automatic date splitting) | Stop at 10,000 |

### Use cases

- **Find tenders to bid on**: open IT tenders over €100k in Île-de-France; every cleaning tender in the Rhône closing in the next 30 days.
- **Daily tender alerts**: schedule the Actor with *Only notices not seen in previous runs* and connect Slack, email or your CRM.
- **Competitive intelligence**: every contract your competitor won in the last 2 years, with buyers and amounts.
- **Sales targeting**: which buyers spend the most in your sector, and who supplies them today (contract renewals are predictable).
- **Pricing**: median contract value for your type of service in your region.
- **Market sizing**: total public spending per sector, department or month.

### Input examples

**Open IT tenders above €100k in Île-de-France departments**

```json
{
    "mode": "tenders",
    "cpvCodes": ["72", "48"],
    "departments": ["75", "92", "93", "94"],
    "minEstimatedValue": 100000,
    "openOnly": true
}
```

**Daily alert: new cleaning tenders in Lyon area** (schedule it daily)

```json
{
    "mode": "tenders",
    "keywords": ["nettoyage", "propreté"],
    "departments": ["69"],
    "onlyNew": true,
    "monitorName": "cleaning-lyon"
}
```

**Contracts won by a competitor in the last 2 years**

```json
{
    "mode": "contracts",
    "winnerName": "Onet",
    "awardedAfter": "2 years",
    "maxResults": 1000
}
```

**Who wins IT contracts in Île-de-France?**

```json
{
    "mode": "analysis",
    "cpvCodes": ["72"],
    "regions": ["11"],
    "awardedAfter": "2025-01-01",
    "groupBy": "winner",
    "maxResults": 50
}
```

### Output

**Tender notice** (one row per notice):

```json
{
    "id": "26-103210",
    "url": "https://www.boamp.fr/pages/avis/?q=idweb:26-103210",
    "noticeType": "Avis de marché",
    "title": "Achat de drones professionnels, pièces détachées et accessoires",
    "buyerName": "Département de la Charente-Maritime",
    "buyerSiret": "22170001600738",
    "buyerContactName": "Service de la Commande Publique",
    "buyerEmail": "proceduredemat.marches@charente-maritime.fr",
    "buyerPhone": "0546317000",
    "deadline": "2026-12-08T16:00:00.000Z",
    "deadlineParisTime": "2026-12-08 17:00",
    "daysLeft": 45,
    "estimatedValue": 164000,
    "durationMonths": 48,
    "mainCpv": { "code": "34711100", "label": "Aeroplanes" },
    "lots": [{ "number": "1", "description": "Drones de traitement…", "estimatedValue": 94000 }],
    "documentsUrl": "https://www.achatpublic.com/sdm/ent2/gen/ficheCsl.action?PCSLID=…"
}
```

**Award result** (BOAMP): `winners`, `awardedAmount`, `award.tendersReceived` and per-lot `award.winners` (name, postal code, amount), parsed from both EU and national notices. `isUnsuccessful` flags procedures declared unsuccessful (*sans suite*, *infructueux*).

**Awarded contract** (DECP): `awardedAt`, `title`, `amount`, `procedure`, `offersReceived`, buyer (`buyerName`, `buyerId`, `buyerCategory`, `buyerDepartmentName`…), winner (`winnerName`, `winnerSiren`, `winnerCategory` PME/ETI/GE, `winnerActivity`, `winnerDistanceKm`…) and `allWinners` for joint contracts.

**Analysis row**: `rank`, `label`, `contracts`, `totalAmount`, `medianAmount`, `sharePct`, `mainCounterpart` (e.g. a winner's main buyer), `firstAwardDate`, `lastAwardDate`.

### Pricing

| Event | Price |
|---|---|
| Tender notice | $0.002 ($2 / 1,000) |
| Awarded contract | $0.001 ($1 / 1,000) |
| Market analysis row | $0.005 |

Free: count previews, notices already seen (alerts), and notices skipped by CPV or value filters.

### Good to know

- **Sources**: [BOAMP open data](https://boamp-datadila.opendatasoft.com) (DILA) and the [consolidated DECP](https://www.data.gouv.fr/fr/datasets/608c055b35eb4e6ee20eb325/) on data.gouv.fr, both under *Licence Ouverte / Etalab 2.0*.
- **Contract amounts** are as declared by buyers. Framework agreements often report their maximum value, which can make totals look large. Aberrant amounts (flagged by the dataset) are excluded by default.
- **DECP** covers contracts over €40,000 (and many smaller ones). A contract won jointly has one row per winner.
- **Estimated value** is published in roughly a third of tender notices; filtering on it excludes notices without one.
- **Alerts** remember up to 50,000 notices per alert name.

### More Actors from this developer

### FAQ

**Can I get notices from before 2026?** Yes. BOAMP data goes back to 2015 and DECP to 2018 (earlier for some buyers).

**How do I get tender alerts by email?** Create a task with `onlyNew` on, schedule it daily, and add an email or Slack integration on the task.

**Can AI agents use it?** Yes, through the Apify API, MCP server, or any integration (Make, Zapier, n8n).

##### Can I use it through the API, Make, Zapier or Google Sheets?

Yes. Every run can be started and read through the [Apify API](https://docs.apify.com/api/v2) (JavaScript and Python clients, CLI, MCP), and Apify integrations connect it to Make, Zapier, n8n, Google Sheets, Slack, webhooks and more.

##### Is it legal to use this data?

The Actor only reads public or official open data and doesn't log in anywhere. Check the source's licence and your local rules (for example GDPR when data concerns people) for your use case; if in doubt, ask a lawyer.

##### Something isn't working, or you need another field?

Open an issue on the **Issues** tab: feedback is read and answered.

# Actor input Schema

## `mode` (type: `string`):

<b>Tenders</b>: notices from BOAMP (open calls for tenders, award results…) with buyer contacts, CPV, estimated value, lots and documents link.<br><b>Awarded contracts</b>: who won which contract and for how much (DECP, 3+ million contracts).<br><b>Market analysis</b>: top winners, buyers, sectors or months for your filters, with totals and market shares.

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

One search per line; a notice matches if it contains <b>all the words</b> of <b>any line</b>. Example: <code>nettoyage</code> and <code>entretien locaux</code>.

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

EU procurement codes, full or partial: <code>72</code> (all IT services), <code>4521</code>, <code>90911000</code>.

## `contractTypes` (type: `array`):

Works, services or supplies.

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

Department codes, e.g. <code>69</code>, <code>75</code>, <code>2A</code>, <code>971</code>. Tenders: the notice's departments. Contracts: the buyer's department or the place of performance.

## `buyerName` (type: `string`):

Part of the buyer's name, e.g. <code>Lyon</code>, <code>CHU</code>, <code>Département du Nord</code>.

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

Default: open calls for tenders only.

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

Keep only calls for tenders whose response deadline hasn't passed.

## `publishedAfter` (type: `string`):

A date (<code>2026-10-01</code>) or a duration (<code>7 days</code>, <code>3 months</code>).

## `publishedBefore` (type: `string`):

A date or a duration, like "Published after".

## `searchIn` (type: `string`):

Searching the whole notice finds more; the title is more precise.

## `families` (type: `array`):

The legal regime, which depends on the estimated value.

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

Notices without an estimated value are excluded when this is set.

## `maxEstimatedValue` (type: `integer`):

Notices without an estimated value are excluded when this is set.

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

Remembers the notices already returned, so a scheduled run only outputs new ones. Combine with a schedule and an email/Slack integration for tender alerts.

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

Keeps separate memories for separate alerts, e.g. <code>cleaning-lyon</code>. Defaults to one memory per set of filters.

## `includeRawNotice` (type: `boolean`):

Adds the complete notice as published (large).

## `awardedAfter` (type: `string`):

A date (<code>2025-01-01</code>) or a duration (<code>12 months</code>).

## `awardedBefore` (type: `string`):

A date or a duration, like "Awarded after".

## `regions` (type: `array`):

Region of the buyer.

## `buyerIds` (type: `array`):

Exact SIRET (14 digits) or SIREN (9 digits, matches all its establishments).

## `buyerCategories` (type: `array`):

Type of public buyer.

## `winnerName` (type: `string`):

Track a competitor, e.g. <code>Onet</code>, <code>Capgemini</code>.

## `winnerIds` (type: `array`):

Exact SIRET (14 digits) or SIREN (9 digits, matches all its establishments).

## `winnerCategories` (type: `array`):

Size category of the winning company (INSEE).

## `minAmount` (type: `integer`):

Contract amount in euros, excluding VAT as declared by the buyer.

## `maxAmount` (type: `integer`):

Contract amount in euros.

## `procedures` (type: `array`):

How the contract was awarded.

## `frameworkOnly` (type: `boolean`):

Keep only framework agreements (accords-cadres), which often run for several years.

## `excludeAbnormalAmounts` (type: `boolean`):

The dataset flags amounts that are clearly wrong (e.g. typos with extra zeros). Recommended for totals and rankings.

## `groupBy` (type: `string`):

One row per winner, buyer, sector, department, month… with contracts, totals and market share.

## `cpvLevel` (type: `string`):

How detailed the sectors are when analysing by CPV.

## `sortBy` (type: `string`):

How the analysis rows are ranked.

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

Notices, contracts or analysis rows.

## `countOnly` (type: `boolean`):

Only count matching notices or contracts and estimate the cost. Nothing is charged.

## Actor input object example

```json
{
  "mode": "tenders",
  "keywords": [
    "nettoyage"
  ],
  "noticeTypes": [
    "APPEL_OFFRE"
  ],
  "openOnly": true,
  "searchIn": "everywhere",
  "onlyNew": false,
  "includeRawNotice": false,
  "awardedAfter": "12 months",
  "frameworkOnly": false,
  "excludeAbnormalAmounts": true,
  "groupBy": "winner",
  "cpvLevel": "2",
  "sortBy": "totalAmount",
  "maxResults": 20,
  "countOnly": false
}
```

# Actor output Schema

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

Tender notices with deadline, value, sector and buyer contact.

## `contracts` (type: `string`):

Contracts with winner, amount and buyer.

## `analysis` (type: `string`):

Ranked analysis rows.

## `results` (type: `string`):

Every field of every row.

# 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 = {
    "mode": "tenders",
    "keywords": [
        "nettoyage"
    ],
    "openOnly": true,
    "awardedAfter": "12 months",
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("yck69/french-public-procurement").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 = {
    "mode": "tenders",
    "keywords": ["nettoyage"],
    "openOnly": True,
    "awardedAfter": "12 months",
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("yck69/french-public-procurement").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 '{
  "mode": "tenders",
  "keywords": [
    "nettoyage"
  ],
  "openOnly": true,
  "awardedAfter": "12 months",
  "maxResults": 20
}' |
apify call yck69/french-public-procurement --silent --output-dataset

```

## MCP server setup

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

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/XO0dbFMHB5OEabEL1/builds/D7o1aRRccfvpxPK57/openapi.json
