# Failed & Relaunched Public Tenders (EU TED + France BOAMP) (`jovianlabs/failed-public-tenders`) Actor

Public procurement lots that closed with no tenders received or all tenders rejected, across the EU (TED), plus open French calls that relaunch an unsuccessful procedure (BOAMP). Second-chance opportunities with little competition.

- **URL**: https://apify.com/jovianlabs/failed-public-tenders.md
- **Developed by:** [Jovian Labs](https://apify.com/jovianlabs) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$20.00 / 1,000 opportunities

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

## Failed & Relaunched Public Tenders (EU TED + France BOAMP)

Every month, thousands of public procurement lots in Europe close **without a winner** because nobody bid or every bid was rejected. Most of them come back, often with less competition, and the buyer is sometimes allowed to negotiate directly. This Actor finds the failed lots **and the open calls that relaunch them**, in every EU country.

**Try it now:** the default input lists the open relaunch calls and failed lots for France. Change the country to DEU, ITA, ESP, POL… or leave it empty for the whole EU (narrow with CPV prefixes for speed).

### What you get

Two kinds of second-chance opportunities, one row each:

| Type | Source | What it is |
|---|---|---|
| Failed lot | TED (all EU/EEA countries) | A lot closed without a winner in a result notice: no tenders received, all tenders rejected, or (optional) only one admissible tender |
| Open relaunch call | TED (all EU/EEA countries) | A call for tenders still open today from the same buyer, with the same CPV code and a similar title as a procedure that failed in the last 12 months. Each match is rated `high` or `medium` and points to the earlier failed notice |
| Open relaunch call | BOAMP (France) | A call for tenders still open today that mentions a previous unsuccessful procedure |

Each row gives the buyer, country, procedure and lot titles, main CPV code, estimated value and currency when published, the reason, the number of tenders received, whether the buyer plans to relaunch, the deadline (relaunch calls) and a link to the official notice.

### Why these opportunities matter

- They have already failed once, often because nobody saw them, the price was too low or the specification too narrow. The relaunch usually draws fewer bidders.
- Under the EU public procurement directive (2014/24/EU, Article 32(2)(a)), when an open or restricted procedure receives no tenders or no suitable tenders, the buyer may use a negotiated procedure without prior publication, provided the initial conditions are not substantially changed. France applies the same rule. A supplier who knows about the failure early can contact the buyer.
- They show where public demand is not being served, by sector and country.

This is not legal advice: rules and practices vary by country and by procedure.

### In numbers (1 January to 18 October 2026)

- About **20,000** EU result notices with at least one lot that received **no tenders at all** (around 110,000 lots), and about **12,500** with **all tenders rejected**.
- In France: about **530** notices with lots that received no tenders, and about **100 open calls** relaunching an unsuccessful procedure on 19 October 2026.
- In Germany on the same day: **134 open calls** matched to an earlier failed procedure of the same buyer.
- Sectors most affected: medical and pharmaceutical supplies, repair and maintenance, vehicles, construction, food, cleaning and waste, engineering and testing services, laboratory instruments, software and IT services.

### Who it is for

- Suppliers and SMEs looking for contracts with little competition
- Bid writers and procurement consultants
- Vendors and analysts looking for unserved public demand in their sector
- AI agents monitoring procurement (callable through the Apify MCP server)

### Input example

```json
{
  "countries": ["FRA", "BEL"],
  "cpvPrefixes": ["72", "48"],
  "keywords": ["logiciel", "plateforme"],
  "daysBack": 60,
  "reasons": ["no-rece", "all-rej"],
  "maxResults": 200
}
```

- `countries`: ISO 3166 alpha-3 codes; empty means all EU/EEA countries. French relaunch calls are included when the list is empty or contains `FRA`.
- `cpvPrefixes`: e.g. `45` construction, `33` medical, `48` software, `72` IT services, `71` engineering and testing, `90` cleaning and waste.
- `keywords`: titles are in the language of the notice, so use local-language keywords.
- `minEstimatedValue`: keeps only failed lots with a published estimated value at least this high.

**Get alerts:** schedule the Actor daily or weekly in Apify Schedules and connect the dataset to email, Slack, Google Sheets or a webhook through Apify Integrations.

### Output example

```json
{
  "source": "TED",
  "country": "FRA",
  "buyer": "Société nationale SNCF",
  "noticeId": "710767-2026",
  "published": "2026-10-14",
  "procedureTitle": "Prestations de conditionnement, collecte, et traitement des déchets amiantés",
  "lotTitle": "NORD MANCHE",
  "cpv": "90520000",
  "estimatedValue": 831446,
  "currency": "EUR",
  "reasonCode": "all-rej",
  "reason": "All tenders were rejected",
  "tendersReceived": 2,
  "relaunchPlanned": false,
  "url": "https://ted.europa.eu/en/notice/-/detail/710767-2026"
}
```

### Pricing

You pay per opportunity delivered. Set `maxResults` or a maximum cost per run to control spending; the Actor stops cleanly at your limit.

### Data sources and limits

- **TED**, the EU's official tenders journal, through its public search API. eForms result notices are covered (from late 2023).
- **BOAMP**, France's official public procurement bulletin, through the DILA open data service (Licence Ouverte / Etalab).
- Titles and descriptions are in the original language of each notice.
- Estimated values are only available when the buyer published them.
- Relaunch calls are detected by matching (TED: same buyer identifier, same CPV code, similar title, earlier failure) or from the notice text (BOAMP). A `medium` match is worth a quick check of both notices.
- Data quality depends on what buyers declare in their notices; open the official notice before acting.

# Actor input Schema

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

ISO 3166 alpha-3 codes, e.g. FRA, DEU, ITA, ESP, POL. Leave empty for all EU/EEA countries (slower: use CPV prefixes to narrow). French BOAMP relaunch calls are included when the list is empty or contains FRA.

## `cpvPrefixes` (type: `array`):

Keep only lots whose main CPV code starts with one of these prefixes, e.g. 48 (software), 72 (IT services), 71 (engineering, testing), 33 (medical), 45 (construction). Leave empty for all sectors.

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

Keep only items whose title or buyer contains at least one keyword (case-insensitive). Titles are in the language of the notice: use local-language keywords.

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

Result notices published in the last N days (failed lots). Relaunch calls are always the ones still open today.

## `reasons` (type: `array`):

Why the lot was not awarded.

## `includeFailed` (type: `boolean`):

Lots closed without a winner in result notices published in the period.

## `includeRelaunched` (type: `boolean`):

Calls for tenders still open today that relaunch an unsuccessful procedure: in all selected EU countries (TED: same buyer, same CPV code, similar title as an earlier failed procedure from the last 12 months) and in France (BOAMP: calls that mention a previous unsuccessful procedure).

## `minEstimatedValue` (type: `integer`):

Keep only failed lots with an estimated value at least this high, in the notice currency. Lots without a published value are dropped when this is set.

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

Each opportunity delivered is billed once.

## Actor input object example

```json
{
  "countries": [
    "FRA"
  ],
  "daysBack": 30,
  "reasons": [
    "no-rece",
    "all-rej"
  ],
  "includeFailed": true,
  "includeRelaunched": true,
  "maxResults": 100
}
```

# Actor output Schema

## `opportunities` (type: `string`):

One row per failed lot or open relaunch call, with buyer, sector, value, reason and link to the official notice.

# 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 = {
    "countries": [
        "FRA"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jovianlabs/failed-public-tenders").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 = { "countries": ["FRA"] }

# Run the Actor and wait for it to finish
run = client.actor("jovianlabs/failed-public-tenders").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 '{
  "countries": [
    "FRA"
  ]
}' |
apify call jovianlabs/failed-public-tenders --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jovianlabs/failed-public-tenders"
        }
    }
}
```

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/zjmphMoW9Gjb8Rypp/builds/IC7YbBSo4enXnMfFx/openapi.json
