# Changelog of Veille Marchés Publics 🇫🇷🇪🇺 : BOAMP + TED, Alertes & IA (`tagadanar/french-public-tenders`) Actor

- **URL**: https://apify.com/tagadanar/french-public-tenders/changelog.md
- **Full Actor documentation**: https://apify.com/tagadanar/french-public-tenders.md

## Changelog

### 2026-09-08

- **A run can no longer spend more time than it has.** The retry ladder booked
  its worst case up front — five attempts at a 30-40 second timeout plus backoff,
  roughly 165-231 seconds for a single request — under loops with no ceiling.
  Because everything was collected before anything was delivered, a run killed
  by the platform timeout handed back nothing and could not say why.
- Every request now plans against the time actually left. A run that hits its
  limit delivers what it did read and says plainly that the result is PARTIAL,
  naming the sources or entries it never reached — instead of reporting an empty
  search, which is a claim it has not earned.
- A request the source rejects outright (a 4xx that is not a rate limit) leaves
  the ladder at once instead of being retried five times.

### 2026-08-30

- **New TED filters.** `noticeTypes` selects which TED notice families come
  back — contract notice (an open call you can still answer), contract award
  (who won an already-closed contract), prior information (an early heads-up).
  Empty keeps the historical behaviour of returning all of them. `expertQuery`
  hands power users TED's own search language; when set it replaces the
  generated TED query outright instead of being silently ANDed with filters
  they did not ask for. Both are TED-only; BOAMP is untouched. Every notice-type
  code was probed live against api.ted.europa.eu on 2026-08-30 (the API rejects
  an unknown value with HTTP 400, so the list is the register's own vocabulary).
- TED records now carry `noticeType` (the TED form code) instead of a constant
  null: the search asks for the field now that it is filterable.
- Every run ends with a status message built by a pure function from explicit
  counters. A registry that never answered is reported as our outage; "nothing
  survived the filters" is reachable only after records the run actually read;
  a first monitor run says it seeded the bucket; a quiet monitor run says how
  many matches had already been reported. A registry that threw while the other
  one answered is named, so a half-answered run never reads as a complete one.
- README: the pricing table now carries the real numbers — $0.004 per tender
  found ($4 per 1,000), $0.04 per tender AI-scored, $0.001 per run start, with
  the Bronze/Silver/Gold discounts, "platform usage included", and the fact
  that the Anthropic tokens for AI scoring are billed by Anthropic to your own
  key on top. It previously described the three events without a single price.

### 2026-07-12

- Invalid input no longer fails the run. The run now finishes cleanly with a clear explanation in its status message, so a typo or an empty list is easy to spot and fix.
- List inputs now accept datasets piped straight from another scraper: entries
  that are objects are read through their usual key names (url/link,
  query/keyword/title, name/company and similar) instead of being rejected.

### 2026-07-11

- Billing: on paid runs every row is billed before it is written, and a run
  now stops visibly if billing fails instead of continuing unbilled.

### 2026-07-09

- Input is now tolerant of common shapes that previously failed the run: a bare
  string / bare object / delimited string for "sources" is coerced into a list
  instead of erroring. Empty input still errors.

### 2026-07-04

- Published on Apify Store.
- Monitor mode: repeat runs return (and charge) only NEW tenders.
- Slack/webhook alerts and optional AI relevance scoring against your company profile (bring your own Anthropic key).

### 2026-07-03

- Initial release.
- French (BOAMP) and EU-wide (TED) public tenders in one actor.
- Filters: keywords, CPV codes, department, deadline. Official open data, deduplicated.
