# EU Tender Watch: TED Deadlines & Amendments (`glaciological_huddle/eu-ted-tender-watch`) Actor

Watch EU public tenders on TED by buyer country, CPV code and keyword. Get new notices plus change rows when a tracked tender's deadline, estimated value, title or status (award, cancellation) changes, with previous and current values. Dedupes across runs.

- **URL**: https://apify.com/glaciological_huddle/eu-ted-tender-watch.md
- **Developed by:** [Clark Scroggin](https://apify.com/glaciological_huddle) (community)
- **Categories:** Business, Automation, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 tender rows

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 Tender Watch: TED Deadlines & Amendments

> **Unofficial; not affiliated with or endorsed by the European Union, the Publications Office of the EU or TED.** This Actor reads public procurement notices through the official TED Search API (no key, no scraping) at a polite request rate. **Source: TED (Tenders Electronic Daily), © European Union, https://ted.europa.eu — reused under the TED legal notice.**

**Know when a tender you are tracking changes.** Public buyers in the EU publish their tenders on TED, and they keep changing them: the submission deadline is extended, the estimated value or the title is corrected, the procedure is cancelled, or an award notice closes it. TED never edits a notice. Each change is a **new notice** (a change notice, or a later award or cancellation notice of the same procedure), which you have to recognise and compare with the old one yourself.

EU Tender Watch does that comparison for you. Pick buyer countries, CPV codes and keywords and run it on a schedule:

- **New tenders** that match your shortlist come out as `rowType: "new"` rows.
- **Later notices of tenders the watch has already seen** come out as `rowType: "amendment"` rows. Each one lists the fields that changed (`changedFields`) and has the previous and the current value of each: `deadline`, `estimatedValue`, `currency`, `title` and `status` (competition → awarded / closed-no-award / cancelled).
- **Nothing is output twice.** Each watch remembers every notice it has handled, so tomorrow's run brings only what is new or changed since today.

It is built for small suppliers and bid consultants who follow a country / CPV shortlist and do not want to miss a deadline extension or reread a whole TED export every morning.

### What you get

One flat row per notice. Below are real rows from test runs on 2026-11-02 (DEU, CPV 72, IT services).

**A deadline extension** found by a scheduled watch. The buyer's change notice of 2026-10-30 moved the deadline by two weeks; the watch had stored the tender from an earlier notice (744245-2026):

```json
{
  "rowType": "amendment",
  "publicationNumber": "753103-2026",
  "procedureId": "a2ce6c55-af5d-423a-aada-23ff75a67bb6",
  "noticeType": "cn-standard",
  "noticeTypeLabel": "Contract notice",
  "stage": "competition",
  "isChangeNotice": true,
  "changeReasonCode": "cor-buy",
  "changeReasonLabel": "Correction by the buyer",
  "publicationDate": "2026-10-30",
  "title": "UEM OSS/MPC",
  "titleLanguage": "deu",
  "buyerName": "Dataport AöR",
  "buyerCountry": "DEU",
  "buyerCity": "Altenholz",
  "cpvMain": "48000000",
  "cpvCodes": ["48000000", "72267000"],
  "procedureType": "open",
  "contractNature": "supplies",
  "deadline": "2026-11-17T12:00:00+01:00",
  "deadlineType": "tender",
  "daysToDeadline": 14,
  "estimatedValue": null,
  "lotCount": 1,
  "changedFields": ["deadline"],
  "changes": [
    { "field": "deadline", "previous": "2026-11-03T12:00:00+01:00", "current": "2026-11-17T12:00:00+01:00" }
  ],
  "previousDeadline": "2026-11-03T12:00:00+01:00",
  "currentDeadline": "2026-11-17T12:00:00+01:00",
  "previousStatus": "competition",
  "previousPublicationNumber": "744245-2026",
  "tedUrl": "https://ted.europa.eu/en/notice/-/detail/753103-2026",
  "tedUrlOriginal": "https://ted.europa.eu/de/notice/-/detail/753103-2026",
  "xmlUrl": "https://ted.europa.eu/en/notice/753103-2026/xml",
  "pdfUrl": "https://ted.europa.eu/en/notice/753103-2026/pdf",
  "fetchedAt": "2026-11-02T16:23:19.763Z",
  "source": "Source: TED (Tenders Electronic Daily), © European Union, https://ted.europa.eu — reused under the TED legal notice. ..."
}
```

**A status change.** A tender for penetration tests (deadline 2026-11-18) was closed by a result notice with no winner. The watch found it by following up on the tenders it tracks, even though result notices are outside the "competition" filter:

```json
{
  "rowType": "amendment",
  "publicationNumber": "749724-2026",
  "noticeTypeLabel": "Contract award notice",
  "stage": "closed-no-award",
  "awardOutcome": "closed-no-winner",
  "title": "Durchführung von Penetrationstests",
  "buyerName": "Medizinischer Dienst Westfalen-Lippe",
  "changedFields": ["status"],
  "changes": [{ "field": "status", "previous": "competition", "current": "closed-no-award" }],
  "previousDeadline": "2026-11-18T10:00:00+01:00",
  "previousPublicationNumber": "736115-2026",
  "tedUrl": "https://ted.europa.eu/en/notice/-/detail/749724-2026"
}
```

**A new tender** (abridged; amendment fields are `null` / empty on new rows):

```json
{
  "rowType": "new",
  "publicationNumber": "752780-2026",
  "noticeTypeLabel": "Contract notice",
  "stage": "competition",
  "publicationDate": "2026-10-30",
  "title": "Überlassung von Lizenzen des Herstellers Broadcom/CA",
  "titleLanguage": "deu",
  "buyerName": "Phoenics.IT GmbH",
  "buyerCountry": "DEU",
  "buyerCity": "Hannover",
  "cpvMain": "72268000",
  "procedureType": "open",
  "deadline": "2026-11-30T12:00:00+01:00",
  "daysToDeadline": 27,
  "estimatedValue": 216000,
  "currency": "EUR",
  "valueBasis": "procedure",
  "changedFields": [],
  "changes": [],
  "tedUrl": "https://ted.europa.eu/en/notice/-/detail/752780-2026"
}
```

#### The columns

- `rowType`: `new` (first notice of this procedure the watch has seen) or `amendment` (a later notice of a tracked procedure).
- `stage` is the status this notice shows: `planning`, `competition`, `awarded`, `closed-no-award`, `direct-award-intent`, `contract-modification`, `completion`, `cancelled` or `other`. A change notice whose reason is a cancellation (`cancel`, `cancel-intent`) is `cancelled`. A result notice is `closed-no-award` only when every lot reports "closed, no winner"; `awardOutcome` gives the detail (`winner-selected`, `partly-awarded`, `closed-no-winner`, `no-winner-yet`).
- `deadline` is the **earliest** submission deadline across all lots, in ISO 8601 with the buyer's UTC offset (a plain date when TED has no time). When no tender deadline is published yet (restricted or negotiated procedures), it is the request-to-participate deadline, and `deadlineType` says which one it is. `lots` lists each lot's deadline when the notice has 2 or more lots.
- `estimatedValue` is the procedure's estimated value. If the notice gives only lot values, it is their **sum** when all lots use one currency (`valueBasis: "sum-of-lots"`). Values of 0 or 1 are placeholders buyers enter when they do not disclose the value, so they become `null`. `awardedValue` is the total awarded on result notices, when published.
- `title` is the procedure title in **English when the notice has one**, otherwise in the original language (`titleLanguage`, e.g. `deu`, `fra`). Most national tenders exist only in the original language.
- `changes` is a list of `{field, previous, current}` objects; the flat columns `previousDeadline` / `currentDeadline`, `previousValue` / `currentValue`, `previousTitle` and `previousStatus` hold the same information in spreadsheet form. A field that is simply missing from a later notice (an award notice has no deadline, for example) is **not** counted as a change.
- `changeReasonCode` / `changeReasonLabel` / `changeReasonText` on change notices give the buyer's stated reason, e.g. `update-add` "Verlängerung der Angebotsfrist" (deadline extension).
- `tedUrl` is the notice page on ted.europa.eu in the English interface, and `tedUrlOriginal` the same page in the original language. `xmlUrl` is the eForms XML and `pdfUrl` the PDF.
- `buyerName` is the first buyer; `otherBuyersCount` counts the rest in joint procurement. Only organisation-level buyer data is output, never contact persons, e-mail addresses or phone numbers.
- Empty values are `null`, never empty strings.

A `RUN_SUMMARY` record in the run's key-value store has the counts: the query sent, notices matching and scanned, tracked tenders followed up, notices already seen, filtered out or unchanged, new and amendment rows, which fields changed, requests used, why the run stopped and how big the watch memory is.

### Why change rows instead of an export

A TED export gives you every notice as a separate record. To learn that "the deadline of the Dataport tender moved from 3 to 17 November", you have to find the earlier notice of the same procedure, line up the lots and compare dates in two time zones. This Actor keeps, per procedure, only the fields that matter for a bid decision. It compares every later notice with them and writes down only the difference. A follow-up notice that changes none of these fields (for example a corrected document link) is remembered but **not output and not charged**, unless you ask for it.

### How to use it

1. **Pick your shortlist.** `countries` (buyer country, ISO 3-letter: DEU, FRA, ITA, ESP, POL, NLD...), `cpvCodes` (prefixes: `72` all IT services, `722` software, `45` construction) and optionally `keywords` (searched in the notice's full text by TED; add translations, because notices are in the buyer's language).
2. **Optionally narrow new rows:** `deadlineAfter: "today"` keeps only tenders still open; `minEstimatedValue` sets a floor on the estimated value.
3. **Name the watch** (`watchName`). The first run is a baseline: everything in the window is new. A first run with `daysBack: 30` gives the watch a month of history, so later changes can be matched to tenders published before you started.
4. **Schedule it daily** with `daysBack: 3` (covers weekends; already-seen notices cost nothing). TED publishes Monday to Friday.
5. **Connect the output** to Slack, e-mail, Google Sheets, webhooks, Zapier, Make or n8n. Quiet runs push nothing.

#### Example 1: German IT services (the default)

```json
{ "countries": ["DEU"], "cpvCodes": ["72"], "daysBack": 3, "maxItems": 50, "watchName": "de-it-services" }
```

#### Example 2: Open cloud tenders over EUR 500k in France and Benelux

```json
{
  "countries": ["FRA", "BEL", "LUX", "NLD"],
  "cpvCodes": ["72", "48"],
  "keywords": ["cloud", "hébergement", "hosting"],
  "daysBack": 3,
  "deadlineAfter": "today",
  "minEstimatedValue": 500000,
  "watchName": "benelux-fr-cloud"
}
```

#### Example 3: Advanced, any TED expert query

```json
{
  "expertQuery": "buyer-country IN (AUT CHE) AND classification-cpv IN (45*) AND procedure-type=open",
  "daysBack": 3,
  "watchName": "alpine-construction"
}
```

The expert query replaces countries, CPV codes, keywords and stages; the Actor adds the publication-date window and the sort order. Build and test queries on [TED expert search](https://ted.europa.eu/en/search/expert-search).

### Input reference

| Field | Type | Default | What it does |
|---|---|---|---|
| `countries` | string\[] | `["DEU"]` | Buyer countries, ISO 3-letter (2-letter codes are converted). Empty = all. |
| `cpvCodes` | string\[] | `["72"]` | CPV codes or prefixes (2–8 digits; `72200000-7` accepted). Matches main and additional CPV codes. Empty = all. |
| `keywords` | string\[] | \[] | Full-text words or phrases (any of them). |
| `noticeStages` | enum\[] | `competition` | Which notices start a new row: `competition`, `planning`, `result`, `direct-award`, `modification`. Amendments of tracked tenders are always reported. |
| `daysBack` | int 1–30 | 3 | Notices published in the last N days. |
| `deadlineAfter` | date / `today` | none | New rows only: keep tenders with a deadline on or after this date. |
| `minEstimatedValue` | number | none | New rows only: minimum estimated value. |
| `includeMissingValue` | bool | true | With a minimum value set, keep notices that disclose no value. |
| `onlyNew` | bool | true | Watch mode. Off = one-off report of the window, nothing remembered (changes within the window are still detected). |
| `watchName` | string | `default` | Memory key (named key-value store `ted-watch-<name>`). |
| `maxItems` | int | 50 | Max rows (charged events) per run; the rest comes with the next run. |
| `maxNoticesScanned` | int | 1000 | Max notices read from TED per run (250 per request). |
| `followTrackedTenders` | bool | true | Also look up later notices of up to `maxTrackedChecked` open tracked tenders (50 per request), so awards and cancellations are caught even outside your filters. |
| `maxTrackedChecked` | int | 100 | See above. |
| `includeUnchangedFollowUps` | bool | false | Also output follow-up notices that change none of the tracked fields. |
| `expertQuery` | string | none | Advanced TED expert query (replaces the filters above; no `SORT BY`). |

### Pricing

Pay per event: you pay for rows delivered, plus a small start fee.

| Event | Price | When |
|---|---|---|
| Actor start | **$0.005** | Once per run, even when nothing is new |
| `tender-notice` | **$0.003** | Per row in the dataset (new tender or amendment) |

**What a watch costs.** German IT services (DEU, CPV 72, contract notices) had 55 notices in the 3 days before our test and 398 in 30 days. In that window 352 notices became rows and 46 were follow-ups with no tracked change, which are free. That is about 17 rows per business day, ≈ **$0.055 a day** (≈ $1.20 a month). The one-time 30-day baseline cost ≈ $1.06. A narrower shortlist (one CPV group, keywords, `deadlineAfter`) usually costs a few cents a week. Unchanged follow-ups and filtered notices are never charged, and the run stops before the spending limit you set on the run.

### Data source and how the Actor behaves

- **Source:** the official [TED Search API](https://docs.ted.europa.eu/api/latest/search.html) (`POST https://api.ted.europa.eu/v3/notices/search`), which the Publications Office provides openly for data reuse without authentication. No web pages are scraped, no browser and no proxies are used.
- One request returns up to 250 notices. A typical daily run makes **1–4 requests**: the watch query, plus up to 2 follow-up queries for tracked tenders. Requests carry a declared User-Agent (`TedTenderWatch/0.1 ...`) and are spaced at most 2.5 per second. Transient errors (429, 5xx, timeouts) are retried up to 3 times with backoff. A query that TED rejects fails the run immediately, with TED's own explanation.
- The Actor asks only for the fields it outputs. Contact fields (e-mail, phone, contact person) are never requested, and free-text fields are additionally scrubbed of anything that looks like an e-mail address or phone number.
- If one notice in a response is malformed, it is skipped and counted (`errors`) and the run continues. If the response as a whole no longer looks like the documented format, the run fails with a clear message instead of returning empty results.
- **Timing:** TED publishes new notices Monday to Friday in its daily edition (OJ S). Rows appear after TED publishes. **This is not a live feed.**

#### How amendments are detected

- Every notice of an eForms procedure carries the same **procedure identifier**. The watch stores, per procedure, the last values it saw: deadline, value, currency, title, stage and the notice number. Change notices also point to the notice they change; that pointer is used when a notice has no procedure identifier (rare, older forms).
- Each notice is handled once per watch (deduplicated by publication number). Within a run, notices are processed oldest first, so a chain like 03 Nov → 06 Nov → 11 Nov produces two amendment rows, each against the step before.
- The same notice in another language or with a different UTC offset is not a change: deadlines are compared as instants, titles only in the same language, amounts as numbers.
- **Memory size:** about 280 bytes per tracked procedure. Entries not seen for 400 days are dropped, and the store is capped at 12,000 procedures and 30,000 notices (oldest dropped first), so it stays under about 4 MB.

### Limitations

- The **first run is a baseline**: everything in the window is `new`, including the latest change notice of a tender whose original notice is older than the window. Its row is complete (it carries the current deadline), but there is no "previous" to compare with.
- Changes to a tender are matched only if the watch has seen an earlier notice of it. Run it regularly and start with a longer `daysBack` if you need history.
- Only the fields listed above are compared. Other edits (documents, criteria, lot descriptions) appear only through `includeUnchangedFollowUps` and the change reason.
- Per-lot values are shown only when TED's lists line up with the lot list; otherwise the total is reliable but `lots[].estimatedValue` is `null`.
- `keywords` use TED's full-text search, which works in the language of the notice.
- Notices in TED's older pre-eForms format (replaced by eForms in 2023) carry no procedure identifier; changes are then matched only through the change notice's reference, which is less reliable.
- `maxItems` caps rows per run. When a run stops early, the next run continues from where it stopped, without duplicates, as long as the notices are still inside the `daysBack` window.

### FAQ

**Is this legal to use?** TED is the EU's official public procurement journal, and the Publications Office provides the Search API for data reuse. Reuse of EU content generally requires acknowledging the source, which the `source` field on every row and this README do. Check the [TED legal notice](https://ted.europa.eu/en/legal-notice) for the current terms. The Actor uses only the official open API, identifies itself and keeps a low request rate. It outputs no personal contact data. You remain responsible for how you use the data.

**Is it official?** No. It is an independent tool and is not affiliated with or endorsed by the European Union, the Publications Office of the EU or TED. For legally binding information, always check the notice on ted.europa.eu (`tedUrl`) and the buyer's procurement documents.

**Why is a tender I know about missing?** It may not be published on TED yet (below-threshold tenders are often only on national portals), it may be outside `daysBack`, in another stage than `noticeStages`, or excluded by `deadlineAfter` / `minEstimatedValue`, or `maxItems` was reached. `RUN_SUMMARY` has the counts.

**Can I track several shortlists?** Yes. Give each its own `watchName`.

**What does a row cost when nothing changed?** Nothing. Already-seen notices, unchanged follow-ups and filtered notices are not output and not charged; a quiet run costs only the $0.005 start fee.

**Can I reset a watch?** Delete the named key-value store `ted-watch-<watchName>` in your Apify storage, or use a new `watchName`.

### Support

Open an issue on the Actor's **Issues** tab with your input and run ID. Ideas for more tracked fields (for example winner names on award notices) are welcome.

# Actor input Schema

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

3-letter ISO codes of the buyer's country, e.g. DEU, FRA, ITA, ESP, POL, NLD (2-letter codes such as DE or FR are converted). Leave empty for all countries.

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

Common Procurement Vocabulary codes or prefixes. "72" = all IT services, "722" = software programming and consultancy, "72200000" = exactly that code. Matches the main and the additional CPV codes of a notice. Leave empty for all sectors.

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

Words or phrases searched in the full text of the notice by TED (any of them matches), e.g. "cloud", "data centre", "SAP". Notices are mostly in the buyer's language, so add translations (e.g. "Rechenzentrum").

## `noticeStages` (type: `array`):

Which kinds of notices start a new row. Default: calls for competition (contract notices, including their change notices). Later award, cancellation and change notices of tenders the watch already tracks are always reported as amendment rows, whatever you pick here.

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

Read notices published in the last N days (1 to 30). 3 is a good daily setting (it covers weekends); a first run with 30 builds a baseline so later deadline changes and awards can be matched.

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

Optional: keep only new notices with a submission deadline on or after this date (YYYY-MM-DD), or type "today" for tenders that are still open. Notices without a deadline (e.g. award notices) are then left out. Does not apply to amendment rows.

## `minEstimatedValue` (type: `number`):

Optional: keep only new notices whose estimated value is at least this amount (in the notice's currency, usually EUR). Does not apply to amendment rows.

## `includeMissingValue` (type: `boolean`):

Many notices do not disclose a value. With a minimum value set, keep them (on) or drop them (off).

## `onlyNew` (type: `boolean`):

On: remember every notice output under the watch name and never output it again; later notices of the same procedure become amendment rows. Off: one-off report of the whole window (changes are still detected within the window), nothing remembered.

## `watchName` (type: `string`):

Name of the memory used by watch mode. Use one name per shortlist (e.g. "de-it-services"). Runs with the same name share what has been seen.

## `maxItems` (type: `integer`):

Stop after this many rows (each row is one charged event). Rows not output are picked up by the next run in watch mode.

## `maxNoticesScanned` (type: `integer`):

Upper bound on notices read from TED in one run (250 per request), whether or not they become rows.

## `followTrackedTenders` (type: `boolean`):

Also ask TED for later notices of open tenders this watch already tracks (50 procedures per request), so award and cancellation notices are reported even when they would not match your filters.

## `maxTrackedChecked` (type: `integer`):

How many open tracked tenders (most recently seen first) are followed per run.

## `includeUnchangedFollowUps` (type: `boolean`):

A later notice of a tracked tender that changes none of deadline, value, title or status (e.g. a corrected document link) is normally only remembered, not output (and not charged). Turn on to output it as an amendment row with an empty change list.

## `expertQuery` (type: `string`):

Optional TED expert-search query that REPLACES countries, CPV codes, keywords and stages, e.g. buyer-country IN (AUT CHE) AND classification-cpv IN (45\*) AND procedure-type=open. The publication-date window and sorting are added by the Actor (do not use SORT BY). Test it on ted.europa.eu/en/search/expert-search.

## Actor input object example

```json
{
  "countries": [
    "DEU"
  ],
  "cpvCodes": [
    "72"
  ],
  "keywords": [],
  "noticeStages": [
    "competition"
  ],
  "daysBack": 3,
  "includeMissingValue": true,
  "onlyNew": true,
  "watchName": "default",
  "maxItems": 20,
  "maxNoticesScanned": 1000,
  "followTrackedTenders": true,
  "maxTrackedChecked": 100,
  "includeUnchangedFollowUps": false
}
```

# Actor output Schema

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

No description

## `runSummary` (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 = {
    "countries": [
        "DEU"
    ],
    "cpvCodes": [
        "72"
    ],
    "keywords": [],
    "noticeStages": [
        "competition"
    ],
    "daysBack": 3,
    "watchName": "default",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("glaciological_huddle/eu-ted-tender-watch").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": ["DEU"],
    "cpvCodes": ["72"],
    "keywords": [],
    "noticeStages": ["competition"],
    "daysBack": 3,
    "watchName": "default",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("glaciological_huddle/eu-ted-tender-watch").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": [
    "DEU"
  ],
  "cpvCodes": [
    "72"
  ],
  "keywords": [],
  "noticeStages": [
    "competition"
  ],
  "daysBack": 3,
  "watchName": "default",
  "maxItems": 20
}' |
apify call glaciological_huddle/eu-ted-tender-watch --silent --output-dataset

```

## MCP server setup

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

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/Qb5ixDhaKbIHD0cSH/builds/K0aDR3bCRCd2ShnvC/openapi.json
