# EU TED Tenders API: Public Procurement Notices (no key) (`datawharf-tools/eu-ted-tenders`) Actor

Search EU public tenders from TED (Tenders Electronic Daily) by keyword, country, CPV code, notice type, buyer and date. Flat rows with deadlines, values and links. No API key. Not affiliated with the EU. Source: TED, CC BY 4.0.

- **URL**: https://apify.com/datawharf-tools/eu-ted-tenders.md
- **Developed by:** [Datawharf Tools](https://apify.com/datawharf-tools) (community)
- **Categories:** Business, Developer tools, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 results

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 TED Tenders: Search Public Procurement Notices by Keyword, Country, CPV

Search **EU public tenders** from **TED (Tenders Electronic Daily)** through the official, keyless **TED Search API v3**, and get flat rows you can export to JSON, CSV or Excel. It only calls the documented API (no scraping, no proxies, no login). **No API key is needed**, and the default input returns real notices on the first click.

### Who is this for?

- **Bid and tender teams** who want a daily table of new EU contract notices matching their CPV codes, countries or keywords.
- **Exporters and agencies** tracking public procurement in specific member states, or award notices for a competitor's buyers.
- **Analysts and developers** who want TED behind a simple form, schedule and dataset instead of writing a client that handles paging, multilingual fields and retries.
- **Teams that bid in both markets.** It pairs with our SAM.gov Contract Opportunities Actor (US federal bids): same flat-row idea, EU data.

### What you get

One row per notice: `noticeId` (TED publication number, e.g. `775146-2026`), `noticeUuid`, `title` and `titleLanguage` (your preferred language, then English, then the first available), `buyerName`, `buyerCountry` (ISO alpha-3), `cpvCodes`, `noticeType`, `procedureType`, `publicationDate`, `deadline` (earliest lot deadline) and `deadlines`, `estimatedValue` with `estimatedValueCurrency` (when the notice states it; sum of lot values, per-lot detail in `estimatedValuesByLot`), `placeOfPerformance` (plus countries and cities), links (`tedUrl`, `pdfUrl`, `xmlUrl`, `htmlUrl`), the `attribution` line, and `fetchedAt`.

Fields TED does not publish for a notice (for example the deadline of an award notice, or a value that is not stated) come back empty rather than guessed. Every run also saves a `RUN_REPORT` (key-value store) with the query used, requests made, retries and total matching notices.

### Quick test

The default input needs no changes and returns the 20 most recent notices:

```json
{ "maxResults": 20 }
```

### How to use it

1. Set any filters (all optional): keywords, buyer countries, CPV codes, notice types, buyer name, publication dates.
2. Click **Start**, then open the **Overview** table or download the dataset.
3. Schedule it daily with Apify schedules to get new notices as they are published (results are newest first).

### Example inputs

IT-services tenders from German and French buyers, last 30 days (default window):

```json
{ "countries": ["DE", "FR"], "cpvCodes": ["72"], "noticeTypes": ["cn-standard"], "maxResults": 200 }
```

Contract awards mentioning a keyword, over one quarter, titles in German where available:

```json
{ "keywords": ["cybersecurity"], "noticeTypes": ["can-standard"], "publicationFrom": "2026-07-01", "publicationTo": "2026-09-30", "titleLanguage": "de", "maxResults": 500 }
```

Everything a given buyer published recently:

```json
{ "buyerName": "Bundesagentur", "maxResults": 100 }
```

### Use it from code (JavaScript and Python)

JavaScript (`npm install apify-client`):

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('datawharf-tools/eu-ted-tenders').call({ countries: ["DE"], cpvCodes: ["72"], noticeTypes: ["cn-standard"], maxResults: 50 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, 'rows');
```

Python (`pip install "apify-client>=3"`):

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("datawharf-tools/eu-ted-tenders").call(run_input={"countries": ["DE"], "cpvCodes": ["72"], "noticeTypes": ["cn-standard"], "maxResults": 50})
items = list(client.dataset(run.default_dataset_id).iterate_items())
print(len(items), "rows")
```

More examples: https://github.com/datawharf-tools/examples

### Pricing

Pay per result: **$0.40 per 1,000 results ($0.0004 per notice)**, plus a small per-run start fee and standard Apify platform usage. Set the **maximum charge per run** to cap spend; the Actor charges before it saves each batch, so it never returns more rows than your cap allows.

### Limits and behaviour

- **Filters are combined with AND**; several values inside one filter (keywords, countries, CPV codes, notice types) are combined with OR. CPV codes shorter than 8 digits match the whole branch (`72` covers IT services); TED also treats a full 8-digit code such as `72000000` as its whole branch, and a notice matches if any of its lots has a matching CPV, so the `cpvCodes` list of a row can include unrelated codes.
- Keywords use TED's full-text search. Buyer name is a "contains" match.
- Results are newest publication first. Each request returns up to 250 notices; the Actor pages with TED's iteration token, so large result sets are not capped by the 15,000-result page window.
- Notice dates are the publication date. The default window is the last 30 days; the default `maxResults` is 20.
- TED publishes titles in many languages; the title is in your preferred language when available. Titles of many notices are machine-prefixed with country and CPV label by TED.
- Failed requests (HTTP 429 and 5xx, timeouts) are retried with backoff. A rejected query (HTTP 400) stops the run with TED's message. Optional `maxApiCalls` (default 100) bounds requests per run.
- If a run stops part-way, the status message starts with "PARTIAL RESULT" and the rows already saved (and charged) are kept.
- TED asks reusers to stay under its fair-usage limits (the developers' corner states 700 requests per minute); this Actor makes far fewer.

### FAQ

**How do I get EU tenders for one country and CPV code every day?** Set `countries` (for example `["DE"]`), `cpvCodes` (for example `["72"]` for IT services) and `noticeTypes`, save it as a Task and schedule it daily. Results are newest first.

**Can I export TED tenders to Excel or Google Sheets?** Yes, from the dataset (XLSX/CSV/JSON) or with the Google Sheets integration.

**Do I need an API key?** No. The TED Search API is open and keyless.

**Is this scraping?** No. It calls the official Search API only.

**Is the full notice text included?** No, the row has the key fields and links to the notice, PDF, HTML and XML on TED.

**Which notice type codes exist?** TED's standard codes, for example `cn-standard` (contract notice), `can-standard` (contract award notice), `pin-only` (prior information notice). See the TED documentation for the full list.

### Source, license and non-affiliation

**Source: TED – Tenders Electronic Daily, Publications Office of the EU, CC BY 4.0** (https://ted.europa.eu). Data comes from the TED Search API ([documentation](https://docs.ted.europa.eu/api/latest/search.html)). Per the [TED legal notice](https://ted.europa.eu/en/legal-notice), TED content may be reused, including commercially, with appropriate credit; if you republish the data, keep the attribution line (each row carries it) and indicate any changes you make.

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

### Related Actors

- [SAM.gov Contract Opportunities](https://apify.com/datawharf-tools/sam-gov-opportunities) for US federal bids.
- [SEC EDGAR Filings & XBRL Data](https://apify.com/datawharf-tools/sec-edgar-api) for company filings and financials.

### Privacy policy

*Publisher: datawharf-tools. Contact: datawharf@gmail.com. Last updated 2026-11-07.*

- **What we process.** Your run inputs (filters) and the public tender notices the TED API returns, including the buyer names and organisation details TED publishes on them. They go straight into your own run's dataset. No API key or credentials are involved.
- **What we keep.** Nothing. We keep no copy of your inputs or the data returned, and the Actor has no analytics, tracking or third-party sharing. Requests go only to api.ted.europa.eu.
- **Where your data lives.** Your run datasets, key-value records and logs live in your own Apify account under Apify's retention rules and [Apify's privacy policy](https://apify.com/privacy-policy). You control and can delete them at any time.
- **Questions or deletion requests.** Write to datawharf@gmail.com.

# Actor input Schema

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

Words or phrases searched in the full text of notices. Several keywords are combined with OR. Leave empty for all notices.

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

Country of the buying organisation, ISO code with 2 or 3 letters (DE or DEU, FR, PL, ...). Several countries are combined with OR.

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

Common Procurement Vocabulary codes, 2 to 8 digits. A shorter code matches the whole branch (72 = IT services). An 8-digit code also matches notices classified under its sub-codes (TED treats 72000000 like 72); check the cpvCodes column of each row. Several codes are combined with OR.

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

TED notice-type codes, for example cn-standard (contract notice), can-standard (contract award notice), pin-only (prior information notice), cn-social, can-social, subco. Empty = all types.

## `buyerName` (type: `string`):

Part of the buying organisation's name, for example Bundesagentur or Ministry.

## `publicationFrom` (type: `string`):

First publication date, YYYY-MM-DD. Default: 30 days before 'Published to'.

## `publicationTo` (type: `string`):

Last publication date, YYYY-MM-DD. Default: today (UTC).

## `titleLanguage` (type: `string`):

Language for the title and buyer name, as a 2-letter (en, de, fr) or 3-letter (eng, deu) code. If the notice has no text in that language, English is used, then the first available language.

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

Maximum number of notices to return, newest first. You are charged per item returned.

## `maxApiCalls` (type: `integer`):

Safety limit on requests to TED in this run (each request returns up to 250 notices). The run ends cleanly when the limit is reached.

## Actor input object example

```json
{
  "titleLanguage": "en",
  "maxResults": 20,
  "maxApiCalls": 100
}
```

# Actor output Schema

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

All notices in the default dataset (table, CSV, JSON, Excel).

## `report` (type: `string`):

Summary of the run (query, requests used, totals) in the default key-value store.

# 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 = {
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("datawharf-tools/eu-ted-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 = { "maxResults": 20 }

# Run the Actor and wait for it to finish
run = client.actor("datawharf-tools/eu-ted-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 '{
  "maxResults": 20
}' |
apify call datawharf-tools/eu-ted-tenders --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datawharf-tools/eu-ted-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/Lq0Bl9XSAQsvdFsl4/builds/H7PCVgqlWCiC8nC1X/openapi.json
