French public tenders and public procurement notices (marchés publics, appels d'offres) from BOAMP and TED in one deduplicated list, incl. MAPA. Tenders scored to your CPV codes, keywords and départements, with deadlines and match reasons. Daily tender alerts (veille).
README: cross-links and examples, no code or price change (2026-10-08, build 0.1.7)
Product name in the README now matches the Store title ("France Tenders Monitor: BOAMP, TED & Marchés Publics").
New Examples section linking the published example task "French IT tenders (BOAMP + TED) - last 7 days".
"Other Lindenwerk Data Actors" lists all six sibling Actors by their current Store titles and Store URLs.
No change to code, input schema, pricing, events, defaults or output.
All notable changes to the France Public Tenders Monitor (BOAMP + TED) by Lindenwerk Data.
Data-quality update: awardedValue fix and deadline-window filter (2026-10-07)
Fixed: awardedValue / awardedCurrency were filled on open tenders. TED's search API puts the estimated value in
total-value on competition notices, and that showed up as an "awarded" value. Both fields are now null on every
notice that is not an award (result) or contract-modification notice; estimatedValue is unchanged.
New optional inputs minDaysUntilDeadline and maxDaysUntilDeadline (days from the run date to the deadline in
daysUntilDeadline), e.g. "maxDaysUntilDeadline": 21 for tenders due within three weeks. Not set = no filter, so
existing inputs behave exactly as before. When either is set, notices without a published deadline are excluded.
The filter runs before scoring and before anything is pushed, so filtered notices are never charged. Counts appear in
RUN_SUMMARY.excludedByFilter (deadlineTooSoon, deadlineTooFar, noDeadline) and RUN_SUMMARY.deadlineFilter.
Input help: CPV examples 4873 / 72212730 for security software, 7971 marked as guarding services (not IT);
keywords / minScore explain that keywords raise the score, so a high minScore with few keywords can return nothing.
README: warning that an API or AI-agent call without mode runs monitor mode (only new notices since the last run),
with a one-off backfill example; the two new filters are documented.
No change to pricing, events, defaults or output columns.
Reliability update: long backfills keep finished days (2026-10-06, before the first public release)
Fixed: the source time budget was a fixed 210 s and a timeout threw away every day that had already finished
(BOAMP fell back to TED only). Long backfills at 512 MB (1/8 of a CPU core) could hit this.
A source that runs out of time or breaks now keeps what it delivered (finished BOAMP days, TED pages fetched so far). The run
says so: status message starting with PARTIAL DATA, a PARTIAL SOURCE log line with the missing days, and new
RUN_SUMMARY fields sourceStatus, partialSources, missingDays, sourceTimeBudgetSeconds. Only delivered rows
are charged.
Time budget: 210 s for short monitor windows (unchanged), 60 s + 25 s per day for backfills (31 days: 835 s), always
leaving at least 300 s before the run timeout.
About 1.7x less CPU for the same output: compiled XPath look-ups, faster accent folding and a cheap upper-bound
check before fuzzy title matching (identical rows on a 7-day test window). Dedup normalises each title once and
reuses one matcher per TED notice. On Apify (512 MB) the 30-day IT backfill takes ~2.7 min with BOAMP and TED
complete (was ~13 min before the fix, ~4.8 min with it); rows and scores identical.
No change to prices, events, input fields, defaults or output fields.
Listing quality update (2026-10-06, before the first public release)
README: starts with an H2 "What is ...?" (Apify Store shows the Actor name as the page H1), new step-by-step
"How to ..." section (first run, own profile, schedule, integrations, API) and a list of the other Lindenwerk Data Actors.
Input form: fields grouped into sections (Competitor tracking, Date range and sources, Output, Advanced) and a "Quickest try" hint in the form description.
No change to the code, prices, events, output fields or defaults.
0.1 (2026-10-05)
Pre-publication update (2026-10-05, later the same day): Store-test-proof defaults.
The input form prefill is now a stateless 7-day backfill with maxResults 25 (IT profile unchanged). Apify's daily
Store test runs the prefill, so it gets rows on any day. A monitor-mode prefill could return 0 rows on a quiet day,
and 3 failed days in a row mark an Actor "under maintenance". API, task and schedule defaults are unchanged
(monitor, lookbackDays 1, maxResults 200).
New firstRunBackfillDays (default 7, 0 = off): a monitor run with no saved state whose window is empty looks back
7 days once.
More robust against outages: an unexpected error or a hang (210 s budget) in BOAMP or TED no longer crashes the run.
The other source's results are delivered with a warning. If both are unreachable, the run fails cleanly with no
charge and no state change. Empty runs end with a clear status message. RUN_SUMMARY gains firstRun,
firstRunFallbackUsed and failedSources.
Initial release:
First public release.
Sources: BOAMP open data (DILA, Licence Ouverte, Opendatasoft export API: one request per publication day) and the
TED Search API v3 (buyer country FRA).
Parses all three BOAMP formats: European eForms notices (EFORMS, rebuilt from BOAMP's JSON into eForms XML and read
with the same parser as TED), national notices (FNSimple) and adapted procedures (MAPA). Older formats fall back to
BOAMP's index fields.
Cross-source deduplication of BOAMP and TED by eForms notice UUID, then by TED publication number, then a
conservative fuzzy match.
French-aware matching: accent-insensitive keywords, BOAMP descriptors (descripteur_libelle) count like title
words, départements (from BOAMP's code_departement or the buyer's postcode, incl. 2A/2B and DROM), French regions
(names, common abbreviations such as IDF/PACA/AURA, or NUTS prefixes) and market level (eu, national, mapa).
Modes: monitor (only new since last run, per stateKey), backfill (up to 31 days) and awards (winners,
awarded values, number of offers; for national notices extracted conservatively from text, legal entities only).
GDPR: named contacts (M./Mme …), personal e-mail addresses and phone numbers are removed from contacts and free text.
Sole-trader winners on MAPA notices (PersonnePhysique) are never output.
Pay-per-event charging (scored-match, notice) with maxResults and maximum-total-charge stop.
103 offline pytest tests (sanitised real BOAMP fixtures with synthetic names), including pre-publish checks of the Actor definition and pricing.