# DECP Scraper: French Public Contracts Awarded (Marches Publics) (`dltik/decp-fr-scraper`) Actor

Scrape 650K+ awarded French public contracts (DECP) — buyer SIRET, winner SIRET, amount, CPV, procedure. Filter by date, CPV, montant, departement. For B2G prospection, market intel, lead gen. $5/1K records.

- **URL**: https://apify.com/dltik/decp-fr-scraper.md
- **Developed by:** [Walid](https://apify.com/dltik) (community)
- **Categories:** Business, Lead generation, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.00005 / actor start

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## DECP Scraper — 650K+ Awarded French Public Contracts API

⭐ **Bookmark this actor → [apify.com/dltik/decp-fr-scraper](https://apify.com/dltik/decp-fr-scraper)** — Apify ranks by bookmarks, so it directly drives the visibility of this scraper. **One click. No signup beyond your existing Apify account.**

> Scrape **650K+ awarded French public contracts** from **DECP** (Données Essentielles de la Commande Publique — Arrêté du 22 décembre 2022). Get the **buyer SIRET, winner SIRET, contract amount in euros, notification date, CPV code, procedure, duration, location** for every public contract awarded by French communes, départements, regions, hospitals, ministries and public agencies. Filter by **date, CPV, montant, département, buyer, winner**. **No OAuth, no API key, no monthly subscription.**

### What makes this scraper different

| Feature | This DECP scraper | TED-only scrapers | Generic procurement scrapers |
|---|:---:|:---:|:---:|
| French municipal contracts (sub-EU threshold) | ✅ 650K+ | ❌ | ⚠️ shallow |
| Buyer SIRET (joinable to Sirene / Pappers) | ✅ | ❌ | ❌ |
| Winner SIRET (titulaire 1/2/3) | ✅ | ❌ partial | ❌ |
| Contract amount in euros (`montant`) | ✅ structured | ⚠️ rare | ❌ |
| CPV prefix filter (`72`, `45`, `85`...) | ✅ | ✅ | ⚠️ |
| Montant min/max filter | ✅ | ❌ | ❌ |
| Département filter (prefix on `lieu_execution`) | ✅ | ❌ | ❌ |
| Innovative-contract toggle (`marcheinnovant`) | ✅ | ❌ | ❌ |
| Green-procurement toggle (`considérations env.`) | ✅ | ❌ | ❌ |
| Per-record charge (no actor-start fee) | ✅ | ❌ inflated | ✅ |
| Concessions dataset toggle | ✅ | ❌ | ❌ |

### What can this scraper do?

- 🇫🇷 **650K+ awarded French public contracts** from the official DECP feed (Arrêté 22/12/2022, live)
- 🏛️ **Every type of public buyer** — communes, départements, régions, CHU, ministères, agences, syndicats intercommunaux
- 💰 **Structured montant in euros** — filter sub-threshold MAPA, mid-range marchés, mega-contrats by exact value
- 🏢 **Buyer and winner SIRET** — directly joinable to [Sirene](https://apify.com/dltik/pappers-sirene-scraper) for instant company enrichment
- 🎯 **CPV prefix filter** — `72` for IT services, `45` for construction, `85` for health, `50410000` for metrology, etc.
- 🌿 **Green / innovation toggles** — `marcheinnovant=oui` + `considerationsenvironnementales` for ESG-aware prospection
- 🗺️ **Lieu d'exécution code** — INSEE / postcode / département for geo-targeted bidding
- 🚀 **No auth, no quota** — HTTP-only, Opendatasoft Explore v2.1, datacenter proxy optional

### What data can you extract per contract?

| Field | Description |
|---|---|
| `contract_id` | DECP contract identifier (`id`) |
| `objet` | Free-text object of the contract |
| `nature` | Marché / Accord-cadre / Marché subséquent |
| `montant_eur` | Awarded amount, in EUR (numeric) |
| `date_notification` | Date the contract was notified to the winner (YYYY-MM-DD) |
| `annee_notification` | Year extracted from `date_notification` (numeric) |
| `date_publication_donnees` | Date the DECP record was published |
| `acheteur_siret` | 14-digit SIRET of the public buyer |
| `acheteur_nom_resolved` | Buyer name (null — join Sirene to enrich) |
| `titulaire_siret` | 14-digit SIRET of the primary winner (titulaire 1) |
| `titulaire_type_identifiant` | `SIRET`, `TVA`, `UE`, `HORS-UE` |
| `titulaire_nom_resolved` | Winner name (null — join Sirene to enrich) |
| `titulaires_all` | All co-titulaires (1-3) with id + type |
| `code_cpv` | Common Procurement Vocabulary code (8 digits + check) |
| `cpv_label` | CPV human label (null — combine with a CPV reference table) |
| `procedure` | "Procédure adaptée", "Appel d'offres ouvert", "Marché négocié"... |
| `duree_mois` | Contract duration in months |
| `lieu_execution_code` | Execution location code (INSEE / postcode / dept) |
| `lieu_execution_type` | "Code postal", "Code commune", "Code département"... |
| `forme_prix` | Unitaire / Forfaitaire / Mixte |
| `offres_recues` | Number of offers received (proxy for competitiveness) |
| `considerations_sociales` | Social-clauses status |
| `considerations_environnementales` | Environmental-clauses status |
| `marche_innovant` | Boolean — innovation procurement flag |
| `ccag` | CCAG reference (Cahier des Clauses Administratives Générales) |
| `modalites_execution`, `techniques`, `types_prix` | Contract-shape details |
| `origine_france_pct`, `origine_ue_pct` | Stated French / EU origin share |
| `sous_traitance_declaree` | Sub-contracting flag |
| `type_groupement_operateurs` | Joint-venture grouping type |
| `source_publication` | DECP source feed (e.g. "DGFIP – PES MARCHÉ") |
| `source_dataset` | `decp-2022-marches-valides` or `decp-2022-concessions-valides` |
| `source_url` | data.economie.gouv.fr permalink |
| `scraped_at` | UTC timestamp of the run |

### How to scrape DECP in 5 steps

1. **[Create a free Apify account](https://apify.com/sign-up)** — no credit card required.
2. **Open [DECP Scraper](https://apify.com/dltik/decp-fr-scraper)** on Apify Store.
3. **Set your filters** — for example `cpv=["72"]` (IT), `departement="75"` (Paris), `notifiedSince="today-180"`, `montantMin=50000`.
4. **Pick `maxResults`** — start at 20 to validate, scale to 5,000 once happy. Hard cap 10,000 per run (Opendatasoft window).
5. **Click Start** — clean JSON in seconds, exportable to CSV / JSON / Excel from the Apify dataset UI.

### How much does it cost to scrape DECP contracts?

**PAY_PER_EVENT — $0.005 per contract scraped** ($5 per 1,000 results). Failed / empty runs not charged.

| Run size | Contracts | Apify cost | Time |
|---|---|---|---|
| Quick test | 20 | $0.10 | ~3s |
| Standard | 200 | $1.00 | ~15s |
| Deep | 1,000 | $5.00 | ~1 min |
| Massive | 5,000 | $25.00 | ~5 min |

Add `includeConcessions=true` to also pull the small concessions dataset (~600 records, long-term public service delegations).

### Input parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `query` | string | — | Free-text search in `objet` |
| `cpv` | array | `[]` | CPV codes, prefix-matched. `["72"]` = all IT, `["45","85"]` = construction OR health |
| `acheteurSiret` | string | — | Exact buyer SIRET (14 digits) |
| `titulaireSiret` | string | — | Exact winner SIRET — every contract a given company has won |
| `notifiedSince` | string | — | ISO date `YYYY-MM-DD` or `today-N` |
| `notifiedUntil` | string | — | ISO date `YYYY-MM-DD` |
| `montantMin` | integer | — | Minimum contract value (EUR) |
| `montantMax` | integer | — | Maximum contract value (EUR) |
| `lieuExecutionCode` | string | — | Exact location code (INSEE / postcode / dept as published) |
| `departement` | string | — | Two-digit dept prefix on `lieu_execution_code` |
| `procedure` | string | — | Partial match — `adaptee`, `ouvert`, `restreint`, `negocie` |
| `marcheInnovant` | bool | `false` | Keep only `marcheinnovant=oui` |
| `considerationsEnv` | bool | `false` | Keep contracts with environmental clauses |
| `includeConcessions` | bool | `false` | Also pull the concessions dataset (~600 rows) |
| `maxResults` | integer | `50` | 1–10000 |
| `proxyConfig` | object | none | Apify proxy (rarely needed) |

### Output example

```json
{
  "type": "marche",
  "source_dataset": "decp-2022-marches-valides",
  "contract_id": "202424.02",
  "objet": "Prestations relatives au contrôle métrologique des instruments de pesage",
  "nature": "Marché",
  "montant_eur": 40000.0,
  "date_notification": "2024-04-25",
  "annee_notification": 2024,
  "date_publication_donnees": "2024-04-26",
  "acheteur_siret": "25020879000098",
  "titulaire_siret": "34974317900203",
  "titulaire_type_identifiant": "SIRET",
  "titulaires_all": [
    { "id": "34974317900203", "type": "SIRET" }
  ],
  "code_cpv": "50410000-2",
  "procedure": "Procédure adaptée",
  "duree_mois": 48,
  "lieu_execution_code": "02000",
  "lieu_execution_type": "Code postal",
  "forme_prix": "Unitaire",
  "offres_recues": 1,
  "considerations_sociales": "Pas de considération sociale",
  "considerations_environnementales": "Pas de considération environnementale",
  "marche_innovant": true,
  "ccag": "Fournitures courantes et services",
  "source_publication": "DGFIP – PES MARCHÉ",
  "source_url": "https://data.economie.gouv.fr/explore/dataset/decp-2022-marches-valides/table/?q=202424.02",
  "scraped_at": "2026-06-20T14:32:01Z"
}
````

### Use cases

- 🎯 **B2G prospection pipeline** — feed your CRM with every new contract matching your CPV + département; never miss a public buyer who's actively spending in your category.
- 📊 **Win/loss intelligence** — pull every contract awarded to a competitor SIRET (`titulaireSiret`) to learn which buyers they own and what amounts they win at.
- 💼 **Account-based marketing** — pull every contract awarded by a target buyer SIRET (`acheteurSiret`) — see exactly which prestataires they trust and what they spend on each line.
- 🏛️ **Public-spend dashboards** — aggregate `montant_eur` per `code_cpv` × `annee_notification` × `departement` for sector-level dashboards.
- 🌿 **ESG / green-procurement intel** — filter `marcheInnovant=true` or `considerationsEnv=true` to track public buyers leading on innovation and environmental clauses.
- 🤖 **Public-tender bot** — combine with [BOAMP Scraper](https://apify.com/dltik/boamp-fr-scraper) (live calls for tender) for full upstream-to-downstream coverage of the French public procurement funnel.

### Use the actor via API

**Python:**

```python
import requests

run = requests.post(
    "https://api.apify.com/v2/acts/dltik~decp-fr-scraper/run-sync-get-dataset-items",
    headers={"Authorization": "Bearer YOUR_APIFY_TOKEN", "Content-Type": "application/json"},
    json={
        "cpv": ["72"],
        "departement": "75",
        "notifiedSince": "today-180",
        "montantMin": 100000,
        "maxResults": 200,
    },
).json()
print(f"Scraped {len(run)} contracts")
```

**curl:**

```bash
curl -X POST "https://api.apify.com/v2/acts/dltik~decp-fr-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"cpv":["45"],"departement":"13","notifiedSince":"2024-01-01","montantMax":1000000,"maxResults":500}'
```

### FAQ

**What is DECP exactly?**
DECP (Données Essentielles de la Commande Publique) is the legal obligation, since 2018 and reinforced by the Arrêté du 22/12/2022, for every French public buyer to publish the essential data of every awarded contract above €40K (sometimes lower, depending on the buyer category). Data is centralised on `data.economie.gouv.fr`.

**How fresh is the data?**
DECP has a structural 2–6 month publication lag — public buyers consolidate then publish in batches. For real-time call-for-tenders, combine with [BOAMP Scraper](https://apify.com/dltik/boamp-fr-scraper). For EU-threshold tenders, see TED Europa scrapers.

**Is every French public contract included?**
Compliance is enforced unevenly — ~85% of communes publish, ~15% of small communes still don't. Large buyers (régions, ministères, CHU) are very well covered.

**Why is `acheteur_nom_resolved` null?**
DECP only publishes the buyer SIRET, not the name. Join the SIRET with our [Pappers Sirene Scraper](https://apify.com/dltik/pappers-sirene-scraper) or [MCP Pappers server](https://apify.com/dltik/mcp-server-pappers) to enrich with the buyer's legal name, address, and effectif.

**Will I get blocked?**
The `data.economie.gouv.fr` Opendatasoft instance has no anti-bot and no published rate limit. We've never been blocked at moderate volume. Datacenter proxy is the default.

**Can I export to CSV?**
Yes — the Apify dataset UI exports to JSON, CSV, XLSX, RSS and HTML out of the box.

***

⭐ **Found this DECP Scraper useful? [Bookmark it](https://apify.com/dltik/decp-fr-scraper)** — Apify ranks actors by bookmarks, so it's the strongest single signal for Store visibility. One click.

### Other scrapers by dltik

| Actor | What it does | Price |
|---|---|---|
| [BOAMP Scraper](https://apify.com/dltik/boamp-fr-scraper) | French national calls for tender (upstream of DECP) | $0.005/tender |
| [TED Europa Scraper](https://apify.com/dltik/ted-europa-scraper) | EU-threshold public procurement (above DECP) | $0.005/tender |
| [Pappers Sirene Scraper](https://apify.com/dltik/pappers-sirene-scraper) | 26M French companies — enrich SIRETs from DECP | $0.001/result |
| [Pappers MCP Server](https://apify.com/dltik/mcp-server-pappers) | French company data for AI agents (Claude / GPT) | $0.01/tool-call |
| [BODACC Scraper](https://apify.com/dltik/bodacc-fr-scraper) | French commercial court announcements | $0.003/record |
| [Annuaire Administration FR](https://apify.com/dltik/annuaire-administration-fr-scraper) | French gov agencies & contacts | $0.003/org |
| [HATVP Scraper](https://apify.com/dltik/hatvp-fr-scraper) | French elected officials' financial declarations | varies |
| [France Travail Scraper](https://apify.com/dltik/francetravail-scraper) | 700K+ FR public job offers | $0.0015/job |

License: MIT · Author: [dltik](https://apify.com/dltik)

# Actor input Schema

## `query` (type: `string`):

Free-text search in the contract object (objet). Examples: 'voirie', 'restauration scolaire', 'logiciel'. Leave empty to get every contract matching the other filters.

## `cpv` (type: `array`):

Common Procurement Vocabulary codes. Prefix-matched against codecpv. Examples: '72' (IT), '45' (construction), '85' (health), '50410000' (metrology). Multiple = OR.

## `acheteurSiret` (type: `string`):

Exact 14-digit SIRET of the public buyer (mairie, departement, region, CHU, ministry...). Example: '21750001600019' (Mairie de Paris).

## `titulaireSiret` (type: `string`):

Exact 14-digit SIRET of the awarded company (titulaire). Use to track every public contract a given company has won.

## `notifiedSince` (type: `string`):

ISO date (YYYY-MM-DD). Only contracts notified on or after this date. Tip: 'today-30' for the last 30 days. DECP has a typical 2-6 month publication lag — use 6-12 month windows for active prospection.

## `notifiedUntil` (type: `string`):

ISO date (YYYY-MM-DD). Only contracts notified on or before this date. Combine with 'Notified since' for a window.

## `montantMin` (type: `integer`):

Minimum contract value in euros (montant). Useful to skip micro-contracts. Example: 100000 = ignore contracts under 100k.

## `montantMax` (type: `integer`):

Maximum contract value in euros. Useful for sub-threshold (MAPA) targeting where smaller B2G specialists win.

## `lieuExecutionCode` (type: `string`):

INSEE code, postcode, or departement code. The DECP feed mixes types — use the raw code as published. Examples: '75056' (Paris commune), '75001' (Paris postcode), '75' (Paris departement).

## `departement` (type: `string`):

Two-digit French department code, prefix-matched against lieuexecution\_code. Examples: '75' (Paris), '13' (Bouches-du-Rhone), '2A' (Corse-du-Sud). Most municipalities publish a 5-digit postcode that starts with the departement.

## `procedure` (type: `string`):

Partial match on the procedure type. Examples: 'adaptee' (Procedure adaptee / MAPA), 'ouvert' (Appel d'offres ouvert), 'restreint' (Appel d'offres restreint), 'negocie'.

## `marcheInnovant` (type: `boolean`):

Filter on marcheinnovant=oui. Use to find R\&D-flavoured contracts (innovation procurement).

## `considerationsEnv` (type: `boolean`):

Keep only contracts with explicit environmental considerations (green public procurement / RSE).

## `includeConcessions` (type: `boolean`):

Also pull contracts from the decp-2022-concessions-valides dataset (~600 records, long-term public service delegations). Off by default — the main marches dataset already covers 650K+ rows.

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

Maximum contracts to return (newest first). Hard cap of 10000 per run (Opendatasoft window limit) — narrow with filters for large searches. Aliases accepted: 'limit', 'max'. Each result is charged at the per-event price — start small to validate.

## `proxyConfig` (type: `object`):

Optional Apify proxy. The data.economie.gouv.fr endpoint has no anti-bot — proxy is rarely useful unless your egress IP is rate-limited.

## Actor input object example

```json
{
  "cpv": [],
  "marcheInnovant": false,
  "considerationsEnv": false,
  "includeConcessions": false,
  "maxResults": 50,
  "proxyConfig": {
    "useApifyProxy": false
  }
}
```

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("dltik/decp-fr-scraper").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("dltik/decp-fr-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call dltik/decp-fr-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=dltik/decp-fr-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "DECP Scraper: French Public Contracts Awarded (Marches Publics)",
        "description": "Scrape 650K+ awarded French public contracts (DECP) — buyer SIRET, winner SIRET, amount, CPV, procedure. Filter by date, CPV, montant, departement. For B2G prospection, market intel, lead gen. $5/1K records.",
        "version": "0.0",
        "x-build-id": "x2c9qO707Ow55pkdw"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/dltik~decp-fr-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-dltik-decp-fr-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/dltik~decp-fr-scraper/runs": {
            "post": {
                "operationId": "runs-sync-dltik-decp-fr-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/dltik~decp-fr-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-dltik-decp-fr-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "query": {
                        "title": "Keywords",
                        "type": "string",
                        "description": "Free-text search in the contract object (objet). Examples: 'voirie', 'restauration scolaire', 'logiciel'. Leave empty to get every contract matching the other filters."
                    },
                    "cpv": {
                        "title": "CPV codes (prefix match)",
                        "type": "array",
                        "description": "Common Procurement Vocabulary codes. Prefix-matched against codecpv. Examples: '72' (IT), '45' (construction), '85' (health), '50410000' (metrology). Multiple = OR.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "acheteurSiret": {
                        "title": "Buyer SIRET",
                        "type": "string",
                        "description": "Exact 14-digit SIRET of the public buyer (mairie, departement, region, CHU, ministry...). Example: '21750001600019' (Mairie de Paris)."
                    },
                    "titulaireSiret": {
                        "title": "Winner SIRET",
                        "type": "string",
                        "description": "Exact 14-digit SIRET of the awarded company (titulaire). Use to track every public contract a given company has won."
                    },
                    "notifiedSince": {
                        "title": "Notified since",
                        "type": "string",
                        "description": "ISO date (YYYY-MM-DD). Only contracts notified on or after this date. Tip: 'today-30' for the last 30 days. DECP has a typical 2-6 month publication lag — use 6-12 month windows for active prospection."
                    },
                    "notifiedUntil": {
                        "title": "Notified until",
                        "type": "string",
                        "description": "ISO date (YYYY-MM-DD). Only contracts notified on or before this date. Combine with 'Notified since' for a window."
                    },
                    "montantMin": {
                        "title": "Min amount (EUR)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Minimum contract value in euros (montant). Useful to skip micro-contracts. Example: 100000 = ignore contracts under 100k."
                    },
                    "montantMax": {
                        "title": "Max amount (EUR)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum contract value in euros. Useful for sub-threshold (MAPA) targeting where smaller B2G specialists win."
                    },
                    "lieuExecutionCode": {
                        "title": "Location code (commune / postcode / departement)",
                        "type": "string",
                        "description": "INSEE code, postcode, or departement code. The DECP feed mixes types — use the raw code as published. Examples: '75056' (Paris commune), '75001' (Paris postcode), '75' (Paris departement)."
                    },
                    "departement": {
                        "title": "Departement (2-digit prefix)",
                        "type": "string",
                        "description": "Two-digit French department code, prefix-matched against lieuexecution_code. Examples: '75' (Paris), '13' (Bouches-du-Rhone), '2A' (Corse-du-Sud). Most municipalities publish a 5-digit postcode that starts with the departement."
                    },
                    "procedure": {
                        "title": "Procedure label",
                        "type": "string",
                        "description": "Partial match on the procedure type. Examples: 'adaptee' (Procedure adaptee / MAPA), 'ouvert' (Appel d'offres ouvert), 'restreint' (Appel d'offres restreint), 'negocie'."
                    },
                    "marcheInnovant": {
                        "title": "Innovative contracts only",
                        "type": "boolean",
                        "description": "Filter on marcheinnovant=oui. Use to find R&D-flavoured contracts (innovation procurement).",
                        "default": false
                    },
                    "considerationsEnv": {
                        "title": "Environmental considerations only",
                        "type": "boolean",
                        "description": "Keep only contracts with explicit environmental considerations (green public procurement / RSE).",
                        "default": false
                    },
                    "includeConcessions": {
                        "title": "Include concessions",
                        "type": "boolean",
                        "description": "Also pull contracts from the decp-2022-concessions-valides dataset (~600 records, long-term public service delegations). Off by default — the main marches dataset already covers 650K+ rows.",
                        "default": false
                    },
                    "maxResults": {
                        "title": "Max results",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Maximum contracts to return (newest first). Hard cap of 10000 per run (Opendatasoft window limit) — narrow with filters for large searches. Aliases accepted: 'limit', 'max'. Each result is charged at the per-event price — start small to validate.",
                        "default": 50
                    },
                    "proxyConfig": {
                        "title": "Proxy (rarely needed)",
                        "type": "object",
                        "description": "Optional Apify proxy. The data.economie.gouv.fr endpoint has no anti-bot — proxy is rarely useful unless your egress IP is rate-limited.",
                        "default": {
                            "useApifyProxy": false
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
