# EU Tender Qualifier - AI Bid/No-Bid on TED & BOAMP (`bidcompass/eu-tender-qualifier`) Actor

Find open EU public tenders on TED and French BOAMP (appels d'offres, Ausschreibungen, licitaciones, bandi di gara, aanbestedingen), score them against your company profile and get an AI bid/no-bid analysis with reasons and red flags. Alerts when a tender is corrected, postponed or cancelled.

- **URL**: https://apify.com/bidcompass/eu-tender-qualifier.md
- **Developed by:** [BidCompass](https://apify.com/bidcompass) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $9.00 / 1,000 tender or change alert returneds

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

### What does EU Tender Qualifier do?

**EU Tender Qualifier** finds open **public tenders** on [TED (Tenders Electronic Daily)](https://ted.europa.eu) and the French [BOAMP](https://www.boamp.fr), **scores each one against your company profile** (CPV codes, keywords, contract value, deadline), and gives the best ones an **AI bid/no-bid (go/no-go) analysis**: summary, reasons, red flags, eligibility requirements and questions to clarify.

You stop reading hundreds of notices a week. You get a short, ranked list of the tenders worth answering, as JSON, CSV or Excel, or directly in your CRM, Slack or AI agent. Use it for public procurement monitoring and tender alerts: it is an alternative to a TED API or BOAMP API integration, with the qualification step already done.

### Why use EU Tender Qualifier?

- 🎯 **Bid only where you can win.** Every tender gets a 0-100 fit score and a GO / MAYBE / NO_GO verdict with the reasons behind it.
- 🇪🇺 **TED + BOAMP in one run.** TED covers notices above EU thresholds in 30+ countries. BOAMP adds French national and **below-threshold (MAPA) tenders** that never reach TED. Duplicates are removed.
- 🤖 **AI analysis where it matters.** A cheap rule-based score filters everything, then the AI reads only the best tenders and checks them against your profile.
- 🔁 **Set and forget.** Schedule it daily or weekly with "Only new tenders since last run": you only receive what you have not seen yet.
- 🔔 **Never miss a correction.** When a tender you received is corrected, gets a new deadline or is cancelled, you get an alert with the old and new deadline. Outdated versions of a notice are merged, so you never work from a stale deadline.
- 🔌 **Works with your stack.** Apify API, webhooks, Make, n8n, Zapier, Google Sheets, Slack, and AI agents through the Apify MCP server.
- ✅ **Official open data only.** It uses the official TED search API and the BOAMP open-data API (Licence Ouverte). No login, no scraping of protected pages.

### What data does EU Tender Qualifier return?

| Field | Description |
|---|---|
| `goNoGo` | `GO`, `MAYBE` or `NO_GO`. In AI mode, only tenders confirmed by the AI are `GO`; the others keep the rule-based verdict, capped at `MAYBE`. Results are sorted by verdict, then score |
| `fitScore` | 0-100 fit with your profile |
| `title`, `buyer`, `buyerCity`, `country` | What is bought and by whom |
| `placeOfPerformance`, `departments`, `nutsCodes` | Where the work takes place (city, French départements, NUTS regions); `departmentsUncertain` flags buyers that cover several départements |
| `description` | Notice description, up to 3,000 characters |
| `cpvCodes`, `mainCpvCodes`, `matchedCpv`, `matchedKeywords` | Classification codes (all and main) and what matched your profile |
| `contractNatures` | `services`, `supplies` and/or `works` |
| `estimatedValue`, `currency` | Estimated contract value when published |
| `deadline`, `daysToDeadline` | Tender submission deadline |
| `procedureType`, `contractNature`, `lots`, `duration` | Procedure details |
| `reasons`, `redFlags` | Why the tender fits, and what could block you |
| `changeType` | Empty for an original call for tenders; `deadline_extended`, `deadline_brought_forward`, `cancelled` or `corrected` for a correction |
| `previousDeadline`, `changeDescription` | Deadline before the change, and what the buyer changed (as published) |
| `originalNoticeId`, `originalUrl` | The notice that the correction replaces |
| `alreadySent` | `true` when an earlier monitoring run already sent you this tender: the record is a change alert |
| `aiAnalysis.summary`, `.requirements`, `.questionsToClarify` | AI reading of the notice |
| `url`, `pdfUrl` | Official notice page and PDF |

### How to find and qualify public tenders

1. Enter the **CPV codes** of what you sell (for example `72000000` for IT services) and/or a few **keywords** in the notice language (`logiciel`, `maintenance applicative`).
2. Choose the **buyer countries** (ISO-2 codes such as `FR`, `BE`, `DE`). To stay local, add French **départements** (`69`, `38`) or **NUTS regions** for any country (`DE2` = Bavaria, `BE1` = Brussels).
3. Describe your company in **Company profile**: size, skills, certifications, references, what you never bid on.
4. Click **Start**. Open the **Qualified tenders** and **AI analysis** tabs of the output.
5. To monitor tenders, create a **schedule** (daily, with "Published in the last 1 day", or weekly with 7) and turn on **Only new tenders since last run**. Each run then returns the new tenders, plus an alert for every tender you already received that was corrected, postponed or cancelled since the last run.

### How much does it cost to qualify tenders?

The Actor uses **pay-per-event** pricing. You only pay for results:

| Event | Price |
|---|---|
| Qualified tender or change alert returned | **$0.009** ($9 per 1,000) |
| AI bid/no-bid analysis | **$0.075** per tender analysed |
| Actor start | $0.00005 per run (Apify's standard start fee, which covers the first seconds of compute) |

A typical weekly run for an IT company in France and Belgium returns about 20 qualified tenders, with 10 AI analyses: **about $0.93 per week**. Platform usage is included. Tenders below your minimum fit score are neither returned nor charged. Set **Maximum cost per run** in the run options to cap your spend.

### Input

See the **Input** tab for every option. The ones that matter most:

- **CPV codes / Keywords**: at least one is required. Parent CPV codes match their children (`72000000` matches `72267100`). Keywords match **whole words**, ignoring accents, case and plurals (`video` matches `videos`, not `videoprotection`); a match in the title scores higher than one in the description.
- **Exclude keywords**: strong penalty for tenders you never want (for example `travaux`, `nettoyage`).
- **Type of contract**: keep only `services`, `supplies` or `works`. An IT services company picks `services` and stops seeing hardware supply tenders.
- **Main vs secondary CPV**: a match on the notice's **main** CPV (procedure or lot) scores fully; a code listed only as secondary scores 60%. **Exclude CPV codes** penalises notices whose main CPV you never want (`45000000` drops construction works that list your furniture as an extra).
- **At least one keyword required**: drop tenders that match your CPV codes but none of your keywords, handy with broad codes like `72000000`.
- **Translate keywords for foreign notices** (on by default): your keywords are translated once per run into the languages of the selected countries, so `mobilier` also finds `mobiliario` in Spain and `mobili` in Italy.
- **Départements / NUTS regions**: geographic filter applied to TED and BOAMP, on the place of performance (or the buyer's address when no place is published). When a notice names places without a postcode, they are matched to their département with the official geo.api.gouv.fr API. Countries without a regional filter stay whole.
- **Minimum / maximum estimated value (EUR)**: out-of-range tenders get a red flag and a 20-point penalty; turn on **Exclude tenders outside the value range** to drop them. Tenders without a published value are kept, with the reason « value not published: value range not checked ».
- **Analysis mode**: `ai` (default) or `rules` only. **Max AI analyses per run** caps how many tenders the AI reads, best first. In AI mode, a rule-based `GO` the AI did not read becomes `MAYBE`, with the reason, so every `GO` has been checked: raise the cap to read more tenders. The AI judges the deadline against your own **Minimum days before deadline**.
- **Output language**: language of the reasons and red flags (English, French, German), of TED texts when the buyer provides them, and of the AI analysis.
- **Track corrections and cancellations** (on by default): corrected notices are labelled and merged with the version they replace. With **Only new tenders since last run**, tenders you already received are watched until 30 days after their deadline: a correction, a new deadline or a cancellation comes back as an alert (`alreadySent: true`), even if the tender no longer matches your filters. Alerts are not counted in **Max tenders returned** and never use the AI.
- **Run summary**: every run stores a `SUMMARY` record (notices fetched, in your area, qualified, returned, qualified tenders cut by **Max tenders returned**, and a `changes` block: corrections found, outdated versions merged, alerts sent), so you know when to raise the limit.

### Output

You can download the dataset in various formats such as **JSON, HTML, CSV, or Excel**. Example item (real TED notice, profile: IT services company in France and Belgium):

```json
{
  "source": "ted",
  "noticeId": "757815-2026",
  "url": "https://ted.europa.eu/en/notice/-/detail/757815-2026",
  "title": "Accord-cadre relatif à l’évolution et à la maintenance du système d’information de l’IR* Progédo — Maintien en Condition Opérationnelle (MCO) et Tierce Maintenance Applicative (TMA)",
  "buyer": "CNRS DELEGATION PARIS-CENTRE",
  "country": "FR",
  "cpvCodes": [
    "72600000"
  ],
  "procedureType": "open",
  "deadline": "2026-11-30",
  "daysToDeadline": 26,
  "estimatedValue": 500000,
  "currency": "EUR",
  "duration": "48 months",
  "ruleScore": 73,
  "fitScore": 72,
  "goNoGo": "GO",
  "reasons": [
    "CPV 72600000 matches your CPV 72000000, 48000000",
    "Keywords found: maintenance applicative",
    "Estimated value 500,000 EUR"
  ],
  "redFlags": [
    "The notice does not state the technology stack, so Java, Python and cloud fit cannot be confirmed.",
    "Hosting is excluded (Huma-Num) and ProgéLab activities are out of scope, so the cloud role may be limited.",
    "Single-operator framework agreement: purchase volumes and guaranteed revenue are not stated in the notice."
  ],
  "analysisMode": "ai",
  "aiAnalysis": {
    "goNoGo": "GO",
    "fitScore": 72,
    "summary": "The CNRS Délégation Paris-Centre wants a single-operator framework agreement (48 months, estimated 500,000 EUR) for maintenance and application management (MCO and TMA) of the Progédo research data warehouse and catalogue. This is IT services work that matches our public-sector application maintenance experience, though the notice does not name the technology stack.",
    "reasons": [
      "CPV 72600000 (computer support and consultancy) matches our IT services activity, and the contract is services, not hardware.",
      "Estimated value of 500,000 EUR sits at the lower edge of our 500k-1.5M public-sector maintenance references.",
      "Scope covers corrective, evolutive, adaptive and preventive maintenance (TMA), which is our core maintenance offer."
    ],
    "redFlags": [
      "The notice does not state the technology stack, so Java, Python and cloud fit cannot be confirmed.",
      "Hosting is excluded (Huma-Num) and ProgéLab activities are out of scope, so the cloud role may be limited.",
      "Single-operator framework agreement: purchase volumes and guaranteed revenue are not stated in the notice."
    ],
    "requirements": [
      "Open procedure under the French Code de la commande publique (R2124-2, R2161-2 to R2161-5).",
      "Framework agreement with purchase orders, concluded with a single economic operator.",
      "Duration of 48 months."
    ],
    "questionsToClarify": [
      "Which technologies and languages does the existing Progédo system use?",
      "What are the selection criteria and any minimum references or certifications required?"
    ],
    "confidence": "medium",
    "model": "anthropic/claude-haiku-5.5",
    "aiGenerated": true
  }
}
```

Real output of a run on 2026-11-04, lists shortened to three items. The AI confirmed the GO and its red flags are repeated in the main `redFlags` field; the AI text is marked `aiGenerated: true`.

A change alert (real BOAMP correction, shortened). The tender was sent by an earlier monitoring run, and the buyer has since postponed the deadline by four weeks:

```json
{
  "source": "boamp",
  "noticeId": "26-104546",
  "url": "https://www.boamp.fr/pages/avis/?q=idweb:26-104546",
  "title": "MISSIONS DE MAITRISE D'OEUVRE (MOe) POUR LE PROJET D'ALIMENTATION ELECTRIQUE DES NAVIRES « PORTE CONTENEURS » A QUAI - Bassins OUEST - FOS 2XL NORD ET SUD",
  "buyer": "GRAND PORT MARITIME DE MARSEILLE",
  "changeType": "deadline_extended",
  "alreadySent": true,
  "previousDeadline": "2026-11-03",
  "deadline": "2026-12-01",
  "changeDescription": "Date limite de réception des offres : au lieu de 2026-11-03 12:00, lire 2026-12-01 12:00 | DLRO : au lieu de DLRO 03.11.2026 à 12h00, lire Nous vous confirmons qu'une nouvelle version du Dossier de Consultation des Entreprises (DCE V2) a été publiée…",
  "originalNoticeId": "26-73821",
  "originalUrl": "https://www.boamp.fr/pages/avis/?q=idweb:26-73821",
  "reasons": ["Deadline extended: 2026-11-03 -> 2026-12-01"]
}
```

Open the **Corrections and cancellations** tab of the output to see them all.

### Tips

- **Start with rules only** to tune your CPV codes and keywords for free, then switch to `ai`.
- **Keywords in several languages**: translation is automatic when you select countries; you can also add your own variants (for example `Gebäudetechnik` next to `génie climatique`).
- **Too many off-topic results?** Combine **Type of contract**, **At least one keyword required** and **Exclude CPV codes** before raising the minimum fit score.
- **Use several monitoring keys** (for example `it-france`, `it-benelux`) to track several profiles independently.
- **BOAMP notices often have no CPV code**, especially below-threshold (MAPA) ones. Add keywords so they are not missed.
- **Route alerts separately**: in Make, n8n or Zapier, send records with `alreadySent: true` to the person who handles the bid, and new tenders to whoever qualifies them.

### Find public tenders in your language

EU Tender Qualifier covers France fully (BOAMP, including below-threshold MAPA, and TED) and the other EU countries through TED, which publishes tenders above EU thresholds. Your keywords are translated automatically, and the AI analysis can be written in your language.

- **Français.** Veille appels d'offres avec IA : l'Actor trouve les appels d'offres publics du BOAMP (MAPA compris) et de TED Europa, les note face au profil de votre entreprise et donne une analyse go/no-go par IA en français. Un outil de veille des marchés publics, pour toute la France ou par département.
- **Deutsch.** Öffentliche Ausschreibungen finden mit KI: Der Actor durchsucht europaweite Ausschreibungen auf TED (oberhalb der EU-Schwellenwerte), bewertet sie nach Ihrem Unternehmensprofil und liefert eine KI-Analyse auf Deutsch. Nationale Portale wie service.bund.de sind nicht abgedeckt.
- **Español.** Buscar licitaciones públicas de la UE: el Actor busca las licitaciones publicadas en TED (por encima de los umbrales europeos), las puntúa según el perfil de su empresa y ofrece un análisis con IA en español. La Plataforma de Contratación del Sector Público (PLACSP) no está incluida.
- **Italiano.** Bandi di gara europei: l'Actor cerca le gare d'appalto pubbliche pubblicate su TED (sopra le soglie UE), le valuta in base al profilo della vostra azienda e fornisce un'analisi con IA in italiano. I portali nazionali come ANAC non sono coperti.
- **Nederlands.** Europese aanbestedingen van de overheid: de Actor zoekt aanbestedingen op TED (boven de Europese drempelwaarden), beoordeelt ze op basis van uw bedrijfsprofiel en geeft een AI-analyse in het Nederlands. TenderNed wordt niet doorzocht.
- **Polski.** Przetargi publiczne UE: Actor wyszukuje przetargi opublikowane w TED (powyżej progów unijnych), ocenia je według profilu Twojej firmy i przygotowuje analizę AI po polsku. Krajowa Baza Zamówień Publicznych (BZP) nie jest objęta.

### FAQ

#### Where does the data come from?

From the official [TED search API](https://docs.ted.europa.eu/api/latest) of the Publications Office of the EU and the [BOAMP open-data API](https://www.data.gouv.fr/datasets/api-boamp) (Licence Ouverte). Both are public, free and keyless. When a French buyer covers several départements and only names the town of the work, the town is matched to its département with the official [geo.api.gouv.fr](https://geo.api.gouv.fr) API.

#### Why do some notices look off-topic?

Rules read the notice as published. A buyer can code a lot with the wrong CPV (a health-insurance contract coded as cleaning, for example): the rule score then trusts the code. The AI analysis reads the text and catches these cases.

#### Is it legal to use TED and BOAMP tender data?

Yes. Tender notices are published so that companies can find them, under open licences that allow commercial reuse: [TED](https://ted.europa.eu/en/legal-notice) (Publications Office of the EU: notices freely reusable, including commercially, under Commission Decision 2011/833/EU) and [BOAMP](https://www.data.gouv.fr/datasets/boamp) (DILA, Licence Ouverte). If you republish them, cite the source and the retrieval date: every run stores a ready-made attribution line in its `SUMMARY` record.

Notices can contain the name of a buyer's contact person, which is personal data protected by the GDPR. The Actor does not extract contact fields and masks email addresses and phone numbers; do not reuse such data without a legitimate reason. Scores and AI analyses are not official information, and this Actor is not affiliated with the Publications Office, DILA or Apify. To learn more, read Apify's article [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/), and ask a lawyer if in doubt.

#### How are corrections and cancellations detected?

- **TED** republishes a corrected notice in full as a *change notice*: the Actor reads its new deadline and the buyer's description of the change, and links it to the original through the TED procedure identifier. A procedure closed without a winner (all lots `clos-nw` in the result notice) is reported as `cancelled`.
- **BOAMP** publishes short *rectificatif* and *annulation* notices linked to the original one. The new deadline is read from the structured fields when present, otherwise from the text ("au lieu de 03/11/2026, lire 13/11/2026"). Changes to the opening date of tenders or to a site visit are not mistaken for a new deadline.
- About half of BOAMP corrections concern something other than the deadline (tender documents, lots, selection rules). They are reported as `corrected`, with the published text, when they concern a tender you received; for other tenders they are skipped, as the Actor cannot tell whether the tender is still open.
- Award notices are not reported.

#### Does it download tender documents (DCE)?

No. Tender documents are often behind a registration on the buyer's platform, and this Actor never logs in anywhere. The analysis uses the notice text: title, description, lots, selection criteria, value and dates. Each item links to the official notice so you can get the full documents.

#### What is sent to the AI model?

In `ai` mode: your **company profile** and the public text of each analysed notice. Whenever **Translate keywords** is on and countries are selected, in any mode: your keywords, for one translation call. They go through Apify's OpenRouter proxy to Claude Haiku 5.5, the only model accepted (its cost per analysis is known and included in the price), routed only to providers that do not train on prompts. Email addresses and phone numbers found in notices are masked before anything is stored or sent. Do not put confidential or personal data in the company profile. Every AI-written block is marked `aiGenerated: true` in the output. Like every Apify run, the processing takes place in the United States (see the privacy notice). To send nothing to an AI model, use `rules` mode and turn off **Translate keywords**.

#### Can the AI be wrong?

Yes. It reads the notice only and can miss details found in the full tender documents. Every reason must cite an element of the notice, and the `confidence` field tells you how sure it is. Use the verdict to sort, not to decide alone.

#### Can I use it from an AI agent?

Yes. Call it through the Apify API or the Apify MCP server. The input is a small JSON profile and the output is clean, typed JSON.

#### Support

Found a bug or need a new source (for example UK Find a Tender, Spain PLACSP, Germany service.bund.de)? Open an issue in the **Issues** tab.

### Privacy notice

*Last updated: 4 November 2026.*

- **Roles.** Under Apify's [Standard Actor Contract](https://docs.apify.com/legal/standard-actor-contract), you are the controller of any personal data in your input and results. The publisher, **Clément LE BEAU EI** (sole trader, France, trading as BidCompass, contact **contact@le-beau.fr**), is your processor and uses that data only to run the Actor for you. The publisher is the controller only of your messages (Issues tab, email), which it uses to answer you.
- **What is processed.** Your search criteria and, in AI mode, your company profile; public notices from TED and BOAMP, without contact fields and with email addresses and phone numbers masked.
- **Where.** Apify runs the Actor and stores its input and results on Amazon Web Services in the United States (us-east-1 region), as your processor under its [Data Processing Addendum](https://docs.apify.com/legal/data-processing-addendum). The Actor uses Apify's **limited permissions**: it cannot access anything else in your account. In AI mode, your company profile and the analysed notices also go to Apify's OpenRouter proxy and to the model provider (Anthropic by default), both in the United States, routed only to providers that do not train on prompts. Keyword translation, when on, sends your keywords the same way, in any mode. To send nothing to an AI model, use `rules` mode and turn off **Translate keywords**.
- **Other recipients.** The TED and BOAMP official APIs receive your search criteria; geo.api.gouv.fr (French government) receives town names taken from notices when you filter by département.
- **Retention.** The publisher keeps nothing and cannot see your runs unless you share one. Results stay in your Apify account until you delete them.
- **Your rights.** For your runs, you handle requests from the people concerned and the publisher helps you; for your messages, you can ask the publisher for access, rectification or erasure. Write to **contact@le-beau.fr**. You can also complain to your data protection authority (in France, the [CNIL](https://www.cnil.fr)).

### Terms of use

Your use of this Actor is governed by Apify's [Standard Actor Contract](https://docs.apify.com/legal/standard-actor-contract) between you and the publisher. The Actor is a decision aid: always read the official notice and the tender documents before deciding to bid.

# Actor input Schema

## `cpvCodes` (type: `array`):

8-digit CPV codes of what you sell. Parent codes match their children: 72000000 matches every IT service code. Provide CPV codes, keywords, or both.

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

Words or phrases searched as whole words in the tender title and description (accents, case and plurals ignored: 'video' does not match 'videoprotection'). Title hits score higher.

## `excludeKeywords` (type: `array`):

Tenders containing one of these words get a strong penalty (for example: travaux, nettoyage).

## `requireKeyword` (type: `boolean`):

On: a tender is returned only if one of your keywords (or its translation) appears in its title or description. Useful when your CPV codes are broad (72000000 covers all IT services).

## `contractNatures` (type: `array`):

Keep only services, supplies or works contracts. Empty = all. An IT services company would pick services to drop hardware supply tenders.

## `excludeCpvCodes` (type: `array`):

Tenders whose MAIN CPV code falls under one of these get a strong penalty (for example 45000000 to drop construction works that only mention your products as a secondary code).

## `translateKeywords` (type: `boolean`):

Translate your keywords once per run into the languages of the selected buyer countries (one small AI call, included in the price), so a French keyword also finds Spanish or German notices. Needs at least one country selected. This call happens in rules mode too: turn it off to send nothing to an AI model.

## `companyProfile` (type: `string`):

Describe your company in a few lines: size, skills, certifications, references, regions served, what you never bid on. The AI compares each tender with this profile.

## `countries` (type: `array`):

ISO-2 codes of the buyer countries (FR, BE, DE…). Empty = all countries on TED. BOAMP is only used when FR is selected or the list is empty.

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

Optional département codes (for example 69, 38, 2A). French notices from TED and BOAMP are kept only when their place of performance (or, failing that, the buyer's address) is in one of them.

## `nutsCodes` (type: `array`):

Optional NUTS region prefixes to narrow TED notices of their country: DE2 = Bavaria, AT13 = Vienna, BE1 = Brussels, ES51 = Catalonia, FRK2 = Rhône-Alpes. Countries without a region filter stay whole.

## `sources` (type: `array`):

TED covers notices above EU thresholds in 30+ countries. BOAMP adds French national and below-threshold (MAPA) notices; its EU notices are skipped when TED is also selected, to avoid duplicates.

## `publishedWithinDays` (type: `integer`):

Only tenders published in this many days. Use 1 for a daily schedule, 7 for a weekly one.

## `minDaysToDeadline` (type: `integer`):

Skip tenders closing sooner than this, since there is not enough time to answer.

## `minValueEur` (type: `integer`):

Tenders below this estimated value get a red flag and a 20-point penalty. 0 = no minimum. Tenders without a published value are kept.

## `maxValueEur` (type: `integer`):

Tenders above this estimated value get a red flag and a 20-point penalty. 0 = no maximum.

## `strictValueRange` (type: `boolean`):

On: tenders whose published value is outside your range are not returned (tenders without a value are kept). Off: they are returned with a red flag and a 20-point penalty.

## `analysisMode` (type: `string`):

"ai": rule-based score for every tender, plus an AI go/no-go analysis of the best ones. "rules": rule-based score only (cheaper).

## `maxAiAnalyses` (type: `integer`):

AI analysis runs on the best-scored tenders only, up to this number. Each analysis is a paid event.

## `minFitScore` (type: `integer`):

Only tenders whose rule-based score (0-100) reaches this value are returned and charged.

## `maxTenders` (type: `integer`):

Maximum number of qualified tenders pushed to the dataset, best first.

## `language` (type: `string`):

Language of the reasons and red flags (English, French, German; others fall back to English), of TED texts when the buyer provides them, and of the AI analysis.

## `aiModel` (type: `string`):

Model used for the AI analysis and the keyword translation. Only models whose cost per analysis is known and included in the price are offered.

## `onlyNewSinceLastRun` (type: `boolean`):

Remember the tenders already returned and skip them next time. Ideal for a daily or weekly schedule.

## `trackChanges` (type: `boolean`):

Label corrected notices (extended deadline, correction, cancellation) and merge them with the version they replace. With "Only new tenders", you also get an alert when a tender you already received is corrected or cancelled, even if it no longer matches your filters.

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

Name of the memory used by "Only new tenders". Use a different key for each profile you monitor.

## `maxNoticesPerSource` (type: `integer`):

Safety cap on notices downloaded from each source before scoring.

## Actor input object example

```json
{
  "cpvCodes": [
    "72000000",
    "48000000"
  ],
  "keywords": [
    "logiciel",
    "maintenance applicative"
  ],
  "excludeKeywords": [],
  "requireKeyword": false,
  "contractNatures": [],
  "excludeCpvCodes": [],
  "translateKeywords": true,
  "companyProfile": "IT services company, 40 people, based in Lyon. Java, Python and cloud (AWS, Azure). ISO 27001 certified. References: 3 public-sector application maintenance contracts (500k-1.5M EUR). We do not bid on hardware supply.",
  "countries": [
    "FR",
    "BE"
  ],
  "departments": [],
  "nutsCodes": [],
  "sources": [
    "ted",
    "boamp"
  ],
  "publishedWithinDays": 7,
  "minDaysToDeadline": 7,
  "minValueEur": 0,
  "maxValueEur": 0,
  "strictValueRange": false,
  "analysisMode": "ai",
  "maxAiAnalyses": 10,
  "minFitScore": 35,
  "maxTenders": 50,
  "language": "en",
  "aiModel": "anthropic/claude-haiku-5.5",
  "onlyNewSinceLastRun": false,
  "trackChanges": true,
  "stateKey": "default",
  "maxNoticesPerSource": 1500
}
```

# Actor output Schema

## `tenders` (type: `string`):

No description

## `aiAnalysis` (type: `string`):

No description

## `changes` (type: `string`):

No description

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

No description

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

No description

# 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 = {
    "cpvCodes": [
        "72000000",
        "48000000"
    ],
    "keywords": [
        "logiciel",
        "maintenance applicative"
    ],
    "companyProfile": "IT services company, 40 people, based in Lyon. Java, Python and cloud (AWS, Azure). ISO 27001 certified. References: 3 public-sector application maintenance contracts (500k-1.5M EUR). We do not bid on hardware supply.",
    "countries": [
        "FR",
        "BE"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("bidcompass/eu-tender-qualifier").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 = {
    "cpvCodes": [
        "72000000",
        "48000000",
    ],
    "keywords": [
        "logiciel",
        "maintenance applicative",
    ],
    "companyProfile": "IT services company, 40 people, based in Lyon. Java, Python and cloud (AWS, Azure). ISO 27001 certified. References: 3 public-sector application maintenance contracts (500k-1.5M EUR). We do not bid on hardware supply.",
    "countries": [
        "FR",
        "BE",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("bidcompass/eu-tender-qualifier").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 '{
  "cpvCodes": [
    "72000000",
    "48000000"
  ],
  "keywords": [
    "logiciel",
    "maintenance applicative"
  ],
  "companyProfile": "IT services company, 40 people, based in Lyon. Java, Python and cloud (AWS, Azure). ISO 27001 certified. References: 3 public-sector application maintenance contracts (500k-1.5M EUR). We do not bid on hardware supply.",
  "countries": [
    "FR",
    "BE"
  ]
}' |
apify call bidcompass/eu-tender-qualifier --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bidcompass/eu-tender-qualifier"
        }
    }
}
```

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/aFBzexYASYI0bCa9u/builds/xHESiLPH8AQMzcSYW/openapi.json
