# EU Public Tenders (TED) (`jetlaunch/eu-public-tenders-ted`) Actor

Search EU public procurement notices on TED by keyword, CPV code, buyer country, date, notice type and value, with optional lot-level detail and award data.

- **URL**: https://apify.com/jetlaunch/eu-public-tenders-ted.md
- **Developed by:** [Chris O'Byrne](https://apify.com/jetlaunch) (community)
- **Categories:** Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 notice records

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

## EU Public Tenders (TED)

Search public procurement notices published on TED (Tenders Electronic Daily), the official EU journal for public tenders, and get clean structured records you can filter, export and schedule. The Actor uses the official, anonymous TED Search API. It needs no login, no API key and no proxy.

### What does EU Public Tenders (TED) do?

You enter keywords, CPV codes, buyer countries, a publication window, a deadline date, notice types or a minimum value. The Actor sends one expert-search query to TED, pages through the results politely, and returns one dataset item per notice with:

- publication number, publication date, notice type and procedure type
- title and a short description (English when the notice provides it)
- buyer organization name, city and country
- CPV codes
- estimated value and currency, as published
- tender submission deadline (or the deadline to request participation for restricted and negotiated procedures)
- award data on result notices: result value, winning organizations, winner countries, lots awarded
- links to the notice page (HTML), the PDF and the XML on TED
- optional lot-level detail: lot id, title, description, value, deadline and per-lot award status

### Who is it for?

Bid and sales teams who track tenders in their field, consultants and agencies who monitor buyers, market researchers who size public spending, journalists and transparency groups, and developers who want TED data in a simple JSON or CSV feed without learning the TED query syntax.

### How to use it

1. Open the Actor and keep the example input (keyword "software", last 7 days, 20 notices) or change it.
2. Add filters. All filters are combined with AND. Several keywords are combined with OR by default, or with AND if you choose "All keywords".
3. Click Start. Results appear in the Output tab and can be downloaded as JSON, CSV, Excel or HTML, or read through the Apify API.
4. Use a schedule to run the same search every day or week.

### Input

| Field | Meaning |
| --- | --- |
| keywords | Words or exact phrases searched in the notice text |
| keywordMatch | any (OR) or all (AND) |
| cpvCodes | CPV codes, 2 to 8 digits. A code also matches the more specific codes below it |
| buyerCountries | Buyer country as ISO code (DEU, DE) or English name |
| noticeTypes | For example cn-standard (contract notice) or can-standard (contract award notice) |
| minValue and valueCurrency | Minimum estimated value as published, optional currency code. No currency conversion is done |
| publishedWithinDays or publishedSince | Publication window |
| deadlineAfter | Tender deadline (or request-to-participate deadline) on or after this date |
| includeLots | Add lot-level detail |
| maxResults | Notices to return, 1 to 5,000. The default is 20 |

### Output example

```json
{
  "publicationNumber": "729917-2026",
  "publicationDate": "2026-10-21",
  "noticeType": "cn-standard",
  "noticeForm": "competition",
  "procedureType": "neg-w-call",
  "procedureTypeLabel": "Negotiated procedure with prior call for competition",
  "contractNature": ["services"],
  "title": "AeroCore FIDS",
  "titleLanguage": "eng",
  "buyerName": "Swedavia AB",
  "buyerCity": "Stockholm Arlanda",
  "buyerCountry": "SWE",
  "buyerCountryName": "Sweden",
  "cpvCodes": ["72000000", "72300000", "48000000"],
  "mainCpv": "72000000",
  "estimatedValue": 30000000,
  "estimatedValueCurrency": "SEK",
  "valueSource": "procedure",
  "lotCount": 1,
  "award": null,
  "noticeUrl": "https://ted.europa.eu/en/notice/-/detail/729917-2026",
  "pdfUrl": "https://ted.europa.eu/en/notice/729917-2026/pdf",
  "xmlUrl": "https://ted.europa.eu/en/notice/729917-2026/xml"
}
```

Result notices carry an `award` object with `resultValue`, `winnerNames`, `winnerCountries`, `lotsAwarded` and `lotsWithoutWinner`. With lot-level detail switched on, each item also has a `lots` list, and the award object has `lotResults`.

### Pricing

The Actor uses pay-per-event pricing. You pay only for notices that are returned, plus the small platform start fee. A search that matches nothing charges no notice events.

| Event | Price | When it is charged |
| --- | --- | --- |
| Notice record | $0.004 | Once for each notice returned |
| Lot-level extraction | $0.01 | Once for each returned notice that has lot detail, only when "Include lot-level detail" is on |
| Actor start | $0.00005 | Once per run, charged by the platform |

Example: 100 notices without lots cost $0.40 plus the start fee. 100 notices with lots cost up to $1.40. You can set a maximum cost per run in the run options and the Actor stops when that limit is reached.

### Data source, licence and attribution

All data comes from the TED Search API at api.ted.europa.eu, which is open to the public without authentication. According to the TED legal notice, procurement notices can be freely reused for commercial or non-commercial purposes, and TED editorial content is licensed under CC BY 4.0. Please credit the source as "TED, Publications Office of the European Union" and mention any changes you make. The Actor keeps to the fair usage limits TED publishes (about 700 HTTP requests per minute) by sending one request at a time with a pause between requests, which stays well under 100 requests per minute.

This Actor is not affiliated with, endorsed by or sponsored by the European Union, the Publications Office of the European Union or TED. Names are used only to describe the data source.

### Privacy

The Actor returns buyer organization names, cities and countries. It does not extract contact persons, emails or phone numbers. Winner names are organization names as published; when TED flags a winner as a natural person, the names for that notice are withheld and `winnerNamesWithheld` is set to true.

### FAQ

**Do I need a TED account or API key?** No. The search endpoint is anonymous.

**How current is the data?** The Actor returns what the TED Search API returns at the moment of the run. A notice can take some time to appear after the buyer sends it.

**Why is the estimated value empty?** Many notices do not publish a value. The value is reported as published, in the notice currency, with no conversion.

**Why are some lot values empty?** TED sometimes returns fewer value entries than lots. In that case the Actor leaves per-lot values empty instead of guessing, and adds a `lotValuesNote`.

**Which language is the title in?** English when the buyer provided it, otherwise the first language in the notice. The language code is in `titleLanguage`.

**Can I get the full notice text or attachments?** The Actor returns links to the notice HTML, PDF and XML. It does not download them, because the TED website is protected by an access check that the Actor does not try to get around.

### Limitations

- A single search returns at most 15,000 notices because of the TED page-number limit, and this Actor caps one run at 5,000. Narrow the date range to go further.
- Descriptions are shortened to 600 characters, lot descriptions to 400.
- The deadline is the earliest one in the notice. Per-lot deadlines appear in lot-level detail.
- The list of countries in the picker covers Europe and neighbours; other ISO codes can be typed in.

### Support

If something looks wrong or you need another field, open an issue in the Issues tab of this Actor with the run link and the input you used.

# Actor input Schema

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

Words or phrases searched in the notice text (full text search). Each entry can be a single word or an exact phrase such as machine learning. Leave empty to search without a keyword.

## `keywordMatch` (type: `string`):

With several keywords, return notices that contain any of them, or only notices that contain all of them.

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

Common Procurement Vocabulary codes, for example 72000000 for IT services. A code also matches the more specific codes below it. Use 2 to 8 digits, a trailing check digit such as -8 is ignored.

## `buyerCountries` (type: `array`):

Only notices from buyers located in these countries. Pick from the list or type an ISO code (DEU, DE) or the English country name.

## `noticeTypes` (type: `array`):

Restrict to specific notice types, for example contract notices (open tenders) or contract award notices. Leave empty for all types.

## `minValue` (type: `number`):

Keep notices whose estimated value (procedure, lot or notice total) is at least this number. The comparison is on the number as published, with no currency conversion. Combine with the currency field below.

## `valueCurrency` (type: `string`):

Optional three-letter currency code (for example EUR, SEK, PLN). When set, only notices with an estimated value in that currency are returned.

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

Only notices published in the last N days. Ignored when Published since is set.

## `publishedSince` (type: `string`):

Only notices published on or after this date (YYYY-MM-DD). Overrides the last N days setting.

## `deadlineAfter` (type: `string`):

Only notices with a tender submission deadline, or a deadline to request participation, on or after this date (YYYY-MM-DD). Useful for open tenders you can still bid on. Notices without a published deadline are excluded when this is set.

## `includeLots` (type: `boolean`):

Add a lots list to each notice with lot id, title, description, estimated value and deadline, plus per-lot award results where available. Billed as an extra event for each notice that has lots.

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

Maximum number of notices to return (each returned notice is billed). The run stops when this number is reached.

## Actor input object example

```json
{
  "keywords": [
    "software"
  ],
  "keywordMatch": "any",
  "publishedWithinDays": 7,
  "includeLots": false,
  "maxResults": 20
}
```

# Actor output Schema

## `notices` (type: `string`):

Table of procurement notices.

# 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 = {
    "keywords": [
        "software"
    ],
    "publishedWithinDays": 7,
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("jetlaunch/eu-public-tenders-ted").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 = {
    "keywords": ["software"],
    "publishedWithinDays": 7,
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("jetlaunch/eu-public-tenders-ted").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 '{
  "keywords": [
    "software"
  ],
  "publishedWithinDays": 7,
  "maxResults": 20
}' |
apify call jetlaunch/eu-public-tenders-ted --silent --output-dataset

```

## MCP server setup

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

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/mH0vtgXu8gsXmS4Ge/builds/EaF9TnJYr9y0TFceD/openapi.json
