# BODACC France: new notices & SIREN / nouvelles annonces (`wavy_millpond/bodacc-france`) Actor

Monitor official BODACC notices by SIREN, company, department and date; skip prior deliveries. / Veille DILA, nouvelles annonces sans doublons entre runs.

- **URL**: https://apify.com/wavy_millpond/bodacc-france.md
- **Developed by:** [Westbrook](https://apify.com/wavy_millpond) (community)
- **Categories:** Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.50 / 1,000 résultat réel / real results

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

## BODACC France: new commercial notices / nouvelles annonces commerciales

Search the [official BODACC / DILA API](https://www.bodacc.fr/pages/donnees-ouvertes-et-api/) by company name, SIREN, filing department, notice family and publication window. Optional `onlyNew` supports recurring company monitoring with durable history across runs. Independent tool, unaffiliated with DILA.

Recherche dans l’API officielle BODACC / DILA par nom commercial, SIREN, département de dépôt, famille et date. `onlyNew` permet une veille avec historique persistant entre exécutions. Outil indépendant, sans affiliation à la DILA.

### Try it / Essayer

Offline synthetic demo: one clearly marked `isDemo: true` row, no source requests or result charge. Démo fictive sans réseau ni événement facturable ; les filtres et l’historique sont ignorés.

```json
{"mode":"demo"}
```

Live recurring monitoring of creations filed in Paris during the past seven UTC days:
Veille réelle des créations déposées à Paris sur sept jours UTC :

```json
{"mode":"live","departments":["75"],"families":["creation"],"daysBack":7,"maxItems":10,"onlyNew":true,"stateKey":"paris-creations"}
```

Run the same input again: previously delivered notice IDs are skipped without another result event. With `onlyNew: false` (default), each run returns matching notices independently. The first monitoring run returns existing matches in the window, up to the output cap.

Relancer cette entrée : les identifiants déjà livrés sont ignorés sans nouvel événement `result`. `onlyNew: false` par défaut conserve la recherche indépendante par run. Le premier run de veille livre les annonces déjà présentes dans la fenêtre, dans la limite demandée.

### Filters and output / Filtres et sortie

All filters combine with AND; list entries combine with OR. `query` uses ODSQL approximate/prefix search on `commercant` only, not judgments. `sirens` accepts up to 20 nine-digit SIRENs without spaces. Departments refer to filing location. `families` uses official `familleavis` codes such as `creation`; an incorrect code can return zero results. `daysBack`: 1–90 UTC days including today. `maxItems`: 1–1,000 newly emitted rows, subject to budget. With `onlyNew`, candidate pages contain up to 100 rows regardless of the output cap; `scanned` counts inspected rows, excluding an unread page tail after the cap. Ordinary searches retain the requested output page size. Source scanning stops after 100 pages or 10,000 inspected source rows even if most are skipped; check `truncated` and `stopReason`.

Tous les filtres se combinent ; les valeurs d’une liste sont alternatives. `query` recherche uniquement le nom commercial via ODSQL (approximatif/préfixe), pas les jugements. Jusqu’à 20 SIREN de neuf chiffres sans espaces. Les départements désignent le dépôt de la formalité. `families` contient les codes officiels `familleavis` tels que `creation` ; une faute peut donner zéro résultat. `daysBack` : 1 à 90 jours UTC incluant aujourd’hui. `maxItems` : 1 à 1 000 lignes nouvelles émises, selon le budget. Avec `onlyNew`, les pages candidates contiennent jusqu’à 100 lignes ; `scanned` compte les lignes inspectées, sans la fin de page non lue après atteinte du plafond. La recherche ordinaire conserve la taille de page liée au plafond. Au plus 100 pages ou 10 000 lignes inspectées, même si elles sont ignorées ; vérifier `truncated` et `stopReason`.

Rows contain `id`, `companyName`, `sirens`, `publicationDate`, `department`, `familyCode`, `family`, `noticeType`, `city`, official `url`, `source`, exact `sourceApiUrl`, `fetchedAt`, `isDemo`, `attribution`. Export JSON, CSV or Excel through Apify. No raw person objects, contacts, detailed addresses, judgments or annual accounts are extracted. Company names may still identify sole traders. An announcement does not establish a company's present status; consult the notice and corrections.

Chaque ligne contient ces champs normalisés et un lien officiel. Export JSON, CSV ou Excel via Apify. Aucun objet de personnes, contact, adresse détaillée, jugement ou compte annuel n’est extrait. Un nom commercial peut désigner un entrepreneur individuel. Une annonce ne prouve pas la situation actuelle de l’entreprise ; consulter la publication et ses rectifications.

`SUMMARY` reports `emitted`, `skippedPrevious` (historic IDs), `duplicates` (within this run), pages, HTTP attempts, source rows scanned, coverage and failure status. Valid empty results produce no synthetic row. `stateStoreName` identifies the private history storage when successfully opened.

`SUMMARY` fournit les lignes émises, les identifiants antérieurs ignorés (`skippedPrevious`), les doublons du run (`duplicates`), les pages, tentatives HTTP, lignes sources et la couverture. Une erreur reste un échec explicite. Une liste vide valide ne produit aucune ligne fictive. `stateStoreName` identifie le stockage privé de l’historique ouvert avec succès.

### Durable monitoring and failures / Veille persistante et échecs

`stateKey` defaults to `default` and accepts 1–64 letters, digits, `_` or `-`. History belongs to the account, Actor, stateKey and normalized filters (`query` trimmed, lists deduplicated/sorted, departments uppercased, `daysBack`). Changing filters or `stateKey` starts independent history; `maxItems` and moving calendar dates do not change scope. No history is created in demo or with `onlyNew: false`.

`stateKey` vaut `default` par défaut : 1 à 64 lettres, chiffres, `_` ou `-`. L’historique dépend du compte, de l’Actor, de cette clé et des filtres normalisés (nom commercial sans espaces aux extrémités, listes dédoublonnées/triées, départements en majuscules, `daysBack`). Modifier un filtre ou la clé ouvre une veille indépendante. Modifier `maxItems` ou avancer dans le calendrier conserve l’historique. Aucune écriture d’historique en démo ou avec `onlyNew: false`.

Each scope uses a named key-value store and a one-token request queue, both named `bodacc-history-<scope hash>`. History stores only up to **10,000 SHA-256 notice ID hashes**, plus one pending hash and the originating run/dataset references. It never silently evicts IDs: reaching capacity rejects a new delivery. A new stateKey deliberately starts fresh and may bill previous matches again. There is one store/queue pair per filter scope; deleting these storages resets that history. Named storage/resource costs may apply.

Chaque périmètre utilise un key-value store nommé et une file contenant un seul jeton, nommés `bodacc-history-<empreinte>`. L’état conserve au plus **10 000 empreintes SHA-256 d’identifiants**, une livraison en attente et ses références de run/dataset. Aucun identifiant n’est supprimé automatiquement : un historique plein refuse une nouvelle livraison. Une nouvelle clé recommence la veille et peut refacturer les mêmes annonces. Chaque filtre crée sa paire de stockages ; les supprimer efface cet historique. Les coûts de stockage et de ressources peuvent s’appliquer.

[Limited Actor permissions](https://docs.apify.com/actors/development/permissions/migration-guide#the-actor-accesses-named-storages) support named storages first created by this Actor under limited permissions and retain access for subsequent runs by the same user. Keep limited permissions enabled. Pre-existing storages created under another permission context may be inaccessible; errors are not treated as empty history. Local `onlyNew` uses the cloud storage client and needs an authenticated Apify environment; local demo and ordinary search do not need history storage.

Les permissions limitées permettent de créer ces stockages nommés et de les réutiliser pour le même utilisateur. Les conserver activées. Un ancien stockage créé dans un autre contexte de permissions peut être inaccessible ; une erreur ne vaut jamais un historique vide. En local, `onlyNew` utilise le stockage cloud avec authentification Apify ; la démo et la recherche sans historique n’en ont pas besoin.

The [Apify request queue lock](https://docs.apify.com/storage/request-queue#distributivity) rejects concurrent runs on the same scope before querying. A 120-second lease is renewed around source requests and state writes, then released at completion. A lost lock or unavailable/corrupt state fails explicitly. Schedule runs sequentially. Lease expiry after a stalled process and the lack of fencing/transactions across storage, dataset and charging mean **this is not an exactly-once guarantee**.

Le [verrou Apify](https://docs.apify.com/storage/request-queue#distributivity) refuse les runs simultanés sur le même périmètre avant collecte. Le bail de 120 secondes est renouvelé autour des requêtes et écritures, puis libéré. Une perte de verrou ou un état indisponible/corrompu provoque un échec. Planifier les runs en séquence. L’expiration du bail d’un processus bloqué et l’absence de transaction commune entre état, dataset et facturation empêchent toute garantie de livraison/facturation exactement une fois.

Before `pushData(item, 'result')`, a durable `pending` marker is written. After a successful push, its hash becomes `delivered` and pending is cleared. An abort after this checkpoint prevents the push and preserves pending for inspection. Any unresolved pending makes future runs fail before fetching or charging: the Actor cannot tell whether an interrupted push wrote or charged the row. State/dataset/charge are separate operations; a crash can leave a row stored or charged without a completed history checkpoint.

Avant `pushData(item, 'result')`, un marqueur `pending` est persisté. Après succès, l’empreinte rejoint `delivered` et `pending` devient `null`. Un arrêt après ce checkpoint empêche la livraison et conserve le marqueur pour vérification. Un marqueur restant bloque tout nouveau run avant collecte/facturation : une interruption peut laisser une ligne stockée ou facturée sans checkpoint terminé. Ces opérations sont distinctes et ne sont pas atomiques.

**Manual recovery:** stop all runs for this scope and wait for its lock to expire. Open its private `STATE` record; inspect `pending.runId`, `pending.datasetId`, the dataset and charge events. Hash the dataset notice `id` with SHA-256 to compare `pending.idHash`. If delivery AND charging are confirmed successful, add the pending hash once to `delivered` and set `pending: null`. If both are confirmed absent, clear pending to allow retry. If either is uncertain, leave pending intact and reconcile first. Never blindly clear pending or delete the store; these actions can replay and rebill data. Corrupt records require manual repair or an intentional fresh stateKey after inspection.

**Reprise manuelle :** arrêter les runs du périmètre et attendre l’expiration du verrou. Lire `STATE`, vérifier `pending.runId`, `pending.datasetId`, la ligne et les événements facturables ; comparer SHA-256(`id`) à `pending.idHash`. Si livraison ET facturation sont confirmées, ajouter une seule fois l’empreinte à `delivered` et mettre `pending: null`. Si les deux sont confirmées absentes, effacer pending pour réessayer. Si l’une est incertaine, conserver le marqueur et résoudre l’écart d’abord. Ne jamais vider l’état aveuglément : cela peut rejouer et refacturer les annonces. Un état corrompu demande une réparation manuelle ou une nouvelle clé délibérée après inspection.

Resurrecting the same run with an already populated dataset still fails (`EXISTING_DATASET`) before collection, including demo. Inspect its partial results first. onlyNew does not provide an automatic dataset cursor or notice-version tracking; a changed notice with the same ID remains skipped.

Une résurrection avec dataset déjà rempli reste refusée (`EXISTING_DATASET`) avant collecte, même en démo. Consulter le bilan partiel. onlyNew ne fournit ni curseur de reprise du dataset ni suivi des versions : une annonce corrigée avec le même identifiant reste ignorée.

### Price and budget / Prix et budget

**USD 0.0005 per real result (USD 0.50 / 1,000).** Event `result` only, no startup event. Apify's active Pricing tab is authoritative. Skipped historic notices, source-page duplicates and the synthetic demo trigger no result event. A budget cap reduces the requested output before collection; zero affordable results makes no source calls. Resource/storage charges may be separate, including demo runs. Charges and dataset writes are not transactional; see failure recovery above.

**0,0005 USD par résultat réel (0,50 USD / 1 000).** Événement `result`, sans événement de démarrage. L’onglet Pricing actif d’Apify fait foi. Aucun événement pour une annonce ignorée, un doublon ou la démo fictive. Le plafond est réduit avant collecte selon le budget ; zéro résultat finançable signifie zéro appel source. Les ressources et le stockage peuvent être facturés séparément, même en démo. La facturation et l’écriture dataset ne sont pas transactionnelles ; voir la reprise ci-dessus.

### API, MCP and n8n / API, MCP et n8n

Use an Apify credential stored in your environment or automation credentials, never in a workflow export. Utiliser un jeton dans l’environnement ou le gestionnaire d’identifiants, jamais dans un fichier exporté.

```bash
## APIFY_TOKEN is supplied by your environment / fourni par votre environnement.
curl --fail-with-body --request POST \
  'https://api.apify.com/v2/acts/wavy_millpond~bodacc-france/run-sync-get-dataset-items?format=json' \
  --header "Authorization: Bearer ${APIFY_TOKEN}" \
  --header 'Content-Type: application/json' \
  --data @examples/INPUT.monitoring.json
```

MCP server configuration / Configuration serveur MCP (supply authorization through your client's secure credential setup / renseigner l’authentification sécurisée du client) :

```json
{"mcpServers":{"bodacc":{"url":"https://mcp.apify.com/?tools=wavy_millpond/bodacc-france"}}}
```

Ask your agent to run the Actor with `examples/INPUT.monitoring.json`. In n8n import `examples/n8n.monitoring.json`, select an HTTP Header Auth credential with header `Authorization` and value `Bearer <your token>` in its secure credential editor, then enable the daily 09:00 trigger (workflow timezone UTC). The HTTP node waits for completion and returns new dataset rows; an empty second run is normal. Choose a schedule longer than the run duration. For longer runs, start asynchronously via `/runs` and retrieve the default dataset after success.

Demander à l’agent d’exécuter l’Actor avec `examples/INPUT.monitoring.json`. Dans n8n, importer `examples/n8n.monitoring.json`, sélectionner un identifiant HTTP Header Auth avec l’en-tête `Authorization` et `Bearer <votre jeton>` dans l’éditeur sécurisé, puis activer le déclenchement quotidien à 09:00 UTC. Le nœud HTTP attend la fin et renvoie les nouvelles lignes ; un second run vide est normal. Espacer les runs au-delà de leur durée maximale. Pour les longs runs, utiliser `/runs` en asynchrone puis lire le dataset après succès.

### Source limits and checks / Limites source et vérifications

One source request at a time, one second between pages, at most three attempts for network/429/5xx, 20-second timeout and 2 MiB response cap. No proxy, login or browser. The public API can change or fail and notices can move during pagination. Preserve reference, dates and BODACC / DILA attribution; follow [Licence Ouverte 2.0](https://www.etalab.gouv.fr/licence-ouverte-open-licence/) and applicable personal-data obligations. No alert message is sent by this Actor.

Une requête source à la fois, une seconde entre pages, trois tentatives maximum sur panne réseau/429/5xx, timeout 20 s et corps limité à 2 Mio. Aucun proxy, login ni navigateur. L’API publique et ses pages peuvent évoluer. Conserver les références, dates et attribution BODACC / DILA ; respecter la Licence Ouverte 2.0 et les obligations applicables aux données personnelles. Cet Actor n’envoie aucun message d’alerte.

From repository root / Depuis la racine : `npm test`. From this folder / Depuis ce dossier : `npm ci`, prepare demo INPUT / préparer INPUT en démo, `apify validate-schema`, `apify run`. Tests use synthetic fixtures without collection; never commit tokens. Les tests restent synthétiques et sans collecte ; ne jamais versionner de jeton.

# Actor input Schema

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

Demo: one synthetic row without network or result charge; filters and history ignored. / Démo : une ligne fictive sans réseau ni événement ; filtres et historique ignorés. Live: official source / source officielle.

## `maxItems` (type: `integer`):

New rows emitted per run, 1–1,000, subject to budget. Historic skipped IDs do not count. / Lignes nouvelles émises par run, 1 à 1 000, selon budget ; annonces ignorées exclues.

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

Approximate/prefix ODSQL search on commercant only. Empty: no filter. / Recherche ODSQL approximative/préfixe sur commercant uniquement. Vide : aucun filtre.

## `sirens` (type: `array`):

Up to 20 nine-digit SIRENs without spaces; empty means all. / Jusqu’à 20 SIREN de neuf chiffres sans espaces ; vide : tous.

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

Filing departments: 75, 2A, 974. Empty means all. / Départements de dépôt : 75, 2A, 974. Vide : tous.

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

Official familleavis codes, e.g. creation. Empty means all; wrong codes may return zero rows. / Codes officiels familleavis, par exemple creation. Vide : toutes ; erreur de code : résultat possiblement vide.

## `daysBack` (type: `integer`):

Publication window, 1–90 UTC days including today; changing this resets history scope. / Fenêtre de 1 à 90 jours UTC incluant aujourd’hui ; la modifier ouvre un historique indépendant.

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

Skip IDs delivered in prior runs with the same stateKey and normalized filters. Live only; rejects uncertain/corrupt state. / Ignorer les identifiants déjà livrés avec la même clé et les mêmes filtres normalisés. Réel uniquement ; état incertain/corrompu refusé.

## `stateKey` (type: `string`):

Private history namespace, 1–64 letters/digits/*/-. Default: default. New key or changed filters starts fresh and can bill old matches again. / Clé d’historique privé, 1 à 64 lettres/chiffres/*/-. Nouvelle clé ou nouveaux filtres : nouvelle veille et refacturation possible.

## Actor input object example

```json
{
  "mode": "demo",
  "maxItems": 10,
  "query": "",
  "sirens": [],
  "departments": [],
  "families": [],
  "daysBack": 7,
  "onlyNew": false,
  "stateKey": "default"
}
```

# Actor output Schema

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

Normalized notices; isDemo identifies synthetic data. / Avis normalisés ; isDemo identifie toute donnée fictive.

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

Emitted, historic skips, HTTP attempts, coverage, status and history storage name. / Lignes, annonces antérieures ignorées, tentatives HTTP, couverture, statut et nom du stockage d’historique.

# 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("wavy_millpond/bodacc-france").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("wavy_millpond/bodacc-france").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 '{}' |
apify call wavy_millpond/bodacc-france --silent --output-dataset

```

## MCP server setup

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

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/rFeWltf47TsfRYidF/builds/FmkVclsfEzyJajm1v/openapi.json
