# French Public Contract Awards (DECP) – Who Won, Amount, Buyer (`shadow-tools/french-public-procurement-awards-decp`) Actor

Search awarded French public contracts (DECP): winner companies, amounts, buyers, CPV, dates. Incremental monitor mode. Legal entities only. Unofficial, built on open data.

- **URL**: https://apify.com/shadow-tools/french-public-procurement-awards-decp.md
- **Developed by:** [Shadow Tools](https://apify.com/shadow-tools) (community)
- **Categories:** Business, Lead generation, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 contract awards

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 Contract Awards (DECP) – who won, how much, from whom

Call this Actor to find **who won a French public contract, for how much and from which buyer** (DECP open data: winner, amount, CPV code, procedure, notification date). Use it when an AI agent or a human needs past awards for a keyword, buyer, competitor (SIREN), CPV code, region or amount range; use `monitor` mode only for a daily "what is new" job. For open tenders (not yet awarded) use the *Open Tenders Daily* Actor instead.
One call = one answer. **The first call on an unusual query can take 30-60 s** (repeated queries are instant): set a patient client timeout (at least 180 s) and prefer precise keywords and a small `sinceDays` (e.g. 30).

#### Minimal input per mode

| Mode | Minimal input | What comes back |
|---|---|---|
| `search` | `{"keywords": ["nettoyage"], "sinceDays": 30, "maxResults": 5}` | awards matching the filters, newest notification first |
| `monitor` | `{"mode": "monitor", "keywords": ["nettoyage"], "since": "2026-10-20", "maxResults": 5}` | only awards published since `since` / the last run, each delivered once |

Short output (real record, 5 Nov 2026): `{"notificationDate": "2026-10-23", "object": "MS 2025-R080-004-005 Hôpitaux civils de Colmar LOT 4", "cpv": "38000000", "amount": 1420500, "currency": "EUR", "buyerName": "RESEAU DES ACHETEURS HOSPITALIERS", "buyerSiren": "130005010", "winnerName": "CEPHEID EUROPE", "winnerSiren": "444404941", "contractId": "2026F10349", "modificationNumber": 0, "amountFlag": null}` (full record below; every record also carries `attribution` and `extractedAt`).

#### For AI agents (MCP)

- **One call = one answer.** Default `maxResults` is 20; keep it small and raise it only when the run SUMMARY says `capped: true`. Empty input returns the 20 most recent awards of the last 30 days.
- **Be patient, be precise.** Allow 30-60 s (up to a few minutes for many winners to verify). Use `sinceDays` 30-90, precise `keywords` (accents must match: try `ménage` and `menage`), or a `winners` / `buyers` SIREN (9 digits, e.g. `350093704`).
- **Errors fail fast** in the form `Field X invalid: expected Y, got Z, example W` (for example `Field notifiedFrom invalid: expected a date YYYY-MM-DD, got "05/11/2026", example 2026-01-31.`). Fix that field and call again; no record is charged.
- **0 results is not an error.** The run succeeds with an empty dataset and the key-value store record `SUMMARY` carries `note: "0 results: <reason / how to widen the search>"` (for example: increase `sinceDays`, use more general keywords, or all matches were sole traders and were removed). In `monitor` mode 0 results usually means nothing new was published since the last run.
- **Freshness**: awards appear 1 to 2 weeks after notification; sole traders (natural persons) are never returned.

> **Unofficial tool.** It is not affiliated with, or endorsed by, the French State, data.gouv.fr or the producers of the data. It reads the official open data and adds filters, clean field names and an incremental mode.

Search **awarded French public contracts** ("marchés attribués", DECP data): the winning company, the amount, the duration, the buying body, the CPV code, the procedure and the notification date. Or switch to **monitor mode** and receive only the awards published since your last run.

Tender notices tell you what is *about to be* bought. Awards tell you **who actually won and for how much**. This Actor is the awards side; it complements the *Open Tenders Daily* Actor (BOAMP + TED notices) by the same publisher: use tender notices to find opportunities, use awards to study competitors, prices and buyers.

### Who uses it

- **Bid and sales teams**: see which competitors win in your CPV codes and regions, and at what price, before pricing your own offer.
- **Suppliers and subcontractors**: find companies that just won large contracts (they need subcontractors and suppliers); track a given winner by SIREN.
- **Market analysts and journalists**: average amounts per procedure, buyer or department; follow one public buyer's spending.
- **Lead generation**: new public contract winners in a sector, delivered every day with the monitor mode.
- **Public buyers and procurement consultants**: benchmark amounts, durations and number of offers received for similar contracts (same CPV, procedure or region) before launching a tender.
- **Researchers and civic-tech projects**: build datasets on public spending by buyer, region or procedure, with the source licence and attribution in every record.

### What you get

One record per contract **and winner** (a contract with a consortium gives one record per member). Main fields:
`notificationDate`, `publishedDate`, `object`, `cpv`, `procedure`, `contractType`, `amount` (EUR), `durationMonths`, `offersReceived`, `buyerName`, `buyerSiren`, `buyerDepartment`, `buyerRegion`, `winnerName`, `winnerSiren`, `winnerLegalForm`, `winnerSize`, `winnerActivity`, `winnerDepartment`, `contractId`, `modificationNumber`, `amountFlag`, `matchedKeywords`, `attribution`.

**Modifications are handled**: the dataset keeps the latest version of each contract; `modificationNumber` tells which version you got. In monitor mode, a contract modified after you received it is delivered again as a new version.

#### Example output (real run, 5 Nov 2026)

```json
{
  "notificationDate": "2026-10-23",
  "publishedDate": "2026-10-25",
  "object": "MS 2025-R080-004-005 Hôpitaux civils de Colmar\nLOT 4",
  "cpv": "38000000",
  "procedure": "Appel d'offres restreint",
  "amount": 1420500,
  "currency": "EUR",
  "durationMonths": 48,
  "offersReceived": 1,
  "buyerName": "RESEAU DES ACHETEURS HOSPITALIERS",
  "buyerSiren": "130005010",
  "buyerDepartment": "75",
  "winnerName": "CEPHEID EUROPE",
  "winnerSiren": "444404941",
  "winnerLegalForm": "5710",
  "winnerSize": "ETI",
  "contractId": "2026F10349",
  "modificationNumber": 0,
  "amountFlag": null
}
```

(Each record also carries `attribution` and `extractedAt`; shortened here.)

### Quick start

Empty input = the 20 most recent awards of the last 30 days. Examples:

**Cleaning contracts won in Ile-de-France above 100 000 EUR**

```json
{ "keywords": ["nettoyage"], "buyerRegions": ["11"], "minAmount": 100000, "maxResults": 200 }
```

**What does a competitor win? (by SIREN)**

```json
{ "winners": ["350093704"], "sinceDays": 0, "maxResults": 500 }
```

**IT services (CPV 72) awarded by a given buyer**

```json
{ "cpvPrefixes": ["72"], "buyers": ["217500016"], "notifiedFrom": "2026-01-01" }
```

**Daily monitor of new software awards (schedule it once a day)**

```json
{ "mode": "monitor", "keywords": ["logiciel", "informatique"], "cpvPrefixes": ["72"], "maxResults": 500 }
```

#### Filters

| Field | Meaning |
|---|---|
| `keywords` | words in the contract object (any of; case-insensitive; accents must match) |
| `buyers` / `winners` | name fragment **or** SIREN/SIRET (any of) |
| `cpvPrefixes` | CPV prefix, 2 to 8 digits (any of) |
| `buyerDepartments`, `buyerRegions`, `winnerDepartments` | codes (INSEE) |
| `procedures`, `contractTypes` | restricted lists |
| `minAmount`, `maxAmount` | EUR; awards without a declared amount are excluded when a bound is set |
| `excludeAmountAnomalies` | drop amounts the dataset itself flags as suspect/aberrant |
| `notifiedFrom`, `notifiedTo`, `sinceDays` | notification date window (default: last 30 days) |
| `mode`: `monitor`, `since` | incremental delivery of awards **published** after your last run |

Keywords, buyers, winners and CPV prefixes are OR lists; the combinations are run one after the other (at most 30).

### Related Actors

- [Open Tenders Daily – TED, BOAMP & UK Tenders](https://apify.com/shadow-tools/boamp-ted-open-tenders): **notices** (what is open for bids now). This Actor gives the **awards** (who won, for how much). Use the first to find opportunities and this one to study the market.

### Privacy / GDPR by design

This Actor is deliberately built **not** to return natural persons (*entrepreneurs individuels*, craftsmen, liberal professions). This is a design choice made to respect the GDPR.

- Each winner's SIREN is checked against the national company directory (SIRENE open data). An award is kept **only** if the directory confirms a legal entity; the check is **fail-closed**. Sole traders, non-public ("non-diffusible") winners, foreign or missing identifiers and winners that cannot be checked are dropped. On a sample of 1,000 recent awards, 1.6 % were dropped as natural persons and 8.5 % for lacking a usable French identifier. A company named after its founder (e.g. a SELARL) is a legal entity and stays.
- No contact data is output; e-mails and phone numbers in the free-text object are masked.
- Not guaranteed: detection relies on the directory's legal form and status, which can be out of date; free text (object, buyer names) may still contain a name. You remain responsible for your own use of the data.
- The Actor stores nothing about you beyond your run's own dataset and logs. It only keeps, in named stores of your own Apify account, the SIREN legal-entity verdicts (a number and a yes/no reason, no name) and, in monitor mode, the keys of already delivered awards.

### Limits and disclaimer

- **Freshness**: the consolidated dataset is rebuilt daily but buyers publish with delay; expect awards to appear about **1 to 2 weeks** after notification. Not every award is published (very small contracts are exempt).
- **Quality**: data is declared by the buyers; amounts can be wrong (see `amountFlag`), some identifiers are missing. No warranty; check the official source before relying on a record.
- **Speed**: the data comes from a public API that can take 30 to 60 s for the first page of an uncommon query (instant when repeated). Keep `maxResults` moderate or use monitor mode for daily jobs.
- **Source and licence**: DECP (Données essentielles de la commande publique), consolidated dataset published on [data.gouv.fr](https://www.data.gouv.fr/datasets/donnees-essentielles-de-la-commande-publique-consolidees-format-tabulaire), under the **Licence Ouverte 2.0** (Etalab). Every record carries the attribution. Winner legal forms come from the SIRENE register via the "Annuaire des entreprises" open API (Licence Ouverte 2.0).
- Unofficial service, not endorsed by any public body.

### Pricing

Pay per event, no subscription:

| Event | Price | Per 1,000 |
|---|---|---|
| `contract-award`: one award record delivered (one contract and winner) | **0.004 USD** | **4 USD per 1,000 awards** |
| Actor start (once per run) | 0.00005 USD | n/a |

Example: 500 awards cost 2 USD plus the start event. Awards removed by the sole-trader filter or by your filters are not delivered and not charged.

You can cap spend per run with the platform's **Maximum cost per run** setting: the Actor reads it, stops cleanly when the cap is reached and returns the partial results it already delivered (the run needs a cap high enough for at least one award, otherwise it stops with a clear error and nothing is charged).

### En français

Outil non officiel : marchés publics attribués (DECP) avec titulaire, montant, acheteur, CPV, date. Les entrepreneurs individuels (personnes physiques) sont systématiquement exclus. Mode « monitor » pour recevoir chaque jour uniquement les nouvelles attributions. Données : data.gouv.fr, Licence Ouverte 2.0.

# Actor input Schema

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

Pick one. "search" = use when you have a question about past awards (who won, amounts, a buyer, a competitor, a CPV code): returns awards matching your filters, newest first. "monitor" = use only for a recurring (daily) job: returns awards published since the last run (or since 'since'), each delivered once; it keeps state between runs. Allowed values: search, monitor. Default: search.

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

Words or phrases searched in the contract object (free text), e.g. \["nettoyage", "logiciel"]. ANY of them matches (OR). Case-insensitive but accents must match: add both "ménage" and "menage" if needed. Prefer precise keywords (fewer rows to scan, so a faster first call). Empty = no keyword filter.

## `buyers` (type: `array`):

Public buyers as a list: a name fragment (e.g. "REGION OCCITANIE") or a SIREN (9 digits, e.g. 217500016) or a SIRET (14 digits). ANY of them matches (OR). Empty = all buyers.

## `winners` (type: `array`):

Winning companies as a list: a name fragment (e.g. "VIDELIO") or a SIREN (9 digits, e.g. 350093704) or a SIRET (14 digits); use it for competitor tracking. ANY of them matches (OR). Sole traders are never returned. Empty = all winners.

## `cpvPrefixes` (type: `array`):

CPV (Common Procurement Vocabulary) code prefixes as a list of 2 to 8 digit strings, matched as a prefix, e.g. \["72"] = IT services, \["90911"] = cleaning services. ANY of them matches (OR).

## `buyerDepartments` (type: `array`):

List of department codes of the buyer: 2 digits, 3 digits for overseas or 2A/2B for Corsica, e.g. \["75", "69", "2A", "971"]. ANY matches.

## `buyerRegions` (type: `array`):

List of INSEE region codes of the buyer (2-3 digits), e.g. \["11"] = Ile-de-France, 84 = Auvergne-Rhone-Alpes, 93 = Provence-Alpes-Cote d'Azur, 75 = Nouvelle-Aquitaine, 76 = Occitanie. ANY matches.

## `winnerDepartments` (type: `array`):

List of department codes of the winner's registered establishment: 2 digits, 3 digits for overseas or 2A/2B, e.g. \["59"]. ANY matches.

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

Keep only these award procedures; choose from the allowed values (exact French spelling), e.g. \["Appel d'offres ouvert"]. Empty = all procedures.

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

Keep only these contract types; allowed values: Travaux (works), Services, Fournitures (supplies), e.g. \["Services"]. Empty = all types.

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

Keep awards of at least this amount in EUR excl. VAT as declared, integer 0 or more, e.g. 100000. Awards without a declared amount are excluded when a bound is set.

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

Keep awards of at most this amount in EUR, integer 0 or more, e.g. 500000. Awards without a declared amount are excluded when a bound is set.

## `excludeAmountAnomalies` (type: `boolean`):

Set true to drop amounts the dataset flags as suspect or aberrant (compared with similar contracts). Default false: they are kept and the flag is in the field amountFlag.

## `notifiedFrom` (type: `string`):

Search mode: earliest contract notification date. Format YYYY-MM-DD, example 2026-01-01. Empty = use 'Look-back period' (sinceDays). An invalid date makes the run fail with a clear error.

## `notifiedTo` (type: `string`):

Search mode: latest contract notification date. Format YYYY-MM-DD, example 2026-06-30. Empty = no upper bound.

## `sinceDays` (type: `integer`):

Search mode, used when notifiedFrom is empty: how many days back to search, integer 0-36500, e.g. 30 (applied when empty). Keep it small for a fast answer. 0 = the whole history (slow, only with precise filters). The open data lags the real world by about 1 to 2 weeks.

## `since` (type: `string`):

Monitor mode only: first run starts at this publication date. Format YYYY-MM-DD, example 2026-10-01 (empty = 14 days ago). Later runs resume automatically after the last delivered award.

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

Maximum number of award records returned, integer 1-10000, default 20 (keep it small, e.g. 20; raise it only if the run SUMMARY says capped: true). Applies per keyword/buyer/winner/CPV combination, then the union is cut to this total. Your run cost limit also applies.

## Actor input object example

```json
{
  "mode": "search",
  "keywords": [
    "nettoyage"
  ],
  "buyers": [
    "217500016"
  ],
  "winners": [
    "350093704"
  ],
  "cpvPrefixes": [
    "72"
  ],
  "buyerDepartments": [
    "75",
    "69"
  ],
  "buyerRegions": [
    "11"
  ],
  "winnerDepartments": [
    "59"
  ],
  "maxResults": 20
}
```

# Actor output Schema

## `awards` (type: `string`):

Main fields of each award: date, object, winner, amount, buyer, CPV.

## `allFields` (type: `string`):

Every field of every record.

# 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": [
        "nettoyage"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("shadow-tools/french-public-procurement-awards-decp").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": ["nettoyage"] }

# Run the Actor and wait for it to finish
run = client.actor("shadow-tools/french-public-procurement-awards-decp").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": [
    "nettoyage"
  ]
}' |
apify call shadow-tools/french-public-procurement-awards-decp --silent --output-dataset

```

## MCP server setup

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

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/3hNLbHzFLaJxCul4G/builds/BbsHJxTs1WPUcf1RI/openapi.json
