# TED EU Tender Monitor — Search & Delta-Track Tenders (`westerly_breaker/ted-tender-monitor`) Actor

Search EU public procurement notices (TED) by keyword, CPV code, country and date as clean JSON, with a delta mode returning only new tenders per run. Built for logistics/freight bid teams. No API key needed.

- **URL**: https://apify.com/westerly\_breaker/ted-tender-monitor.md
- **Developed by:** [Daniel Posztos](https://apify.com/westerly_breaker) (community)
- **Categories:** Automation
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.01 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## TED EU Tender Monitor — search & delta-track EU public tenders as JSON

**SEO title:** TED EU Tender Monitor — Search Public Tenders as JSON
**SEO description:** Search EU public tenders (TED) by keyword, CPV code, country and date as clean JSON, with a delta mode returning only new tenders per run. Built for logistics/freight bid teams. No API key needed.

Search **TED (Tenders Electronic Daily)** — the official EU public procurement portal — by keyword, CPV code, buyer country, and publication/deadline date, and get clean, structured JSON back instead of TED's own XML/eForms notice format. Add a scheduled run with `mode: "delta"` and get only the tenders you haven't seen before, so you can watch a saved search for new opportunities without re-processing everything every time.

No scraping, no login, no API key: TED's Search API v3 is public and unauthenticated.

### Why this exists

TED's own Search API is real and free, but not turnkey:
- Its query language ("expert query") is a small custom DSL with undocumented gotchas (see "TED API discoveries" below) — dates in `YYYYMMDD`, not ISO-8601; countries in ISO alpha-3, not alpha-2; response field types that don't always match what TED's own OpenAPI spec declares.
- Responses are nested, multi-language objects (a title is `{"eng": "...", "deu": "...", ...}` for all 24 EU languages) rather than a flat row.
- There's no "give me only what's new since last time" mode — every scheduled run gets everything again, and building your own dedup layer is exactly the kind of undifferentiated work this actor exists to remove.

This actor wraps all of that: one flat JSON object per tender, one input schema, and a delta mode with its own persistent "already seen" tracking.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `keywords` | array of strings | — | Full-text search terms, OR'ed together (any match). E.g. `["logistics", "freight forwarding"]`. Cannot contain `"` or `\`. |
| `cpv_codes` | array of strings | — | [CPV](https://simap.ted.europa.eu/web/simap/cpv) codes, 2/4/6/8 digits (chapter/group/class/full), e.g. `"60"` (transport services), `"6024"` (freight transport by road), `"63120000"` (storage and warehousing). The official `-N` check-digit suffix is accepted and ignored. |
| `countries` | array of strings | `["DE", "HU"]` | ISO 3166-1 **alpha-2** buyer-country codes, e.g. `"DE"`, `"HU"`. This is the contracting authority's country, not the notice's publication language. |
| `published_after` | string (`"YYYY-MM-DD"`) | `"2026-01-01"` | Only notices published on/after this date. |
| `deadline_before` | string (`"YYYY-MM-DD"`) | — | Only notices whose earliest tender-submission deadline is on/before this date. Omit to not filter by deadline (also returns notice types with no deadline at all, e.g. contract award notices). |
| `mode` | string | `"full"` | `"full"`: every matching tender every run. `"delta"`: only tenders not already returned by a previous run with the exact same `keywords`/`cpv_codes`/`countries`/date filters. See "Delta mode" below. |
| `max_items` | integer | `20` | Max tenders to return (and charge for) per run, 1–500. |

At least one of `keywords`, `cpv_codes`, or `countries` is required — `published_after`/`deadline_before` narrow a search, they don't define one on their own.

**Why `published_after` defaults to a fixed `"2026-01-01"` instead of a relative "N days ago":** a static JSON Schema default can't compute "today minus 90 days" — it can only be a fixed value. A fixed, sufficiently-recent-when-written date keeps matching plenty of notices for a long time after this actor was built (TED publishes hundreds of notices a day), which is what actually matters for a default Run/daily health-check to keep succeeding — not that the date stays "recent" forever. If this actor is still running years from now and the default Run starts returning few/no results, that default is the thing to bump, not a sign of a bug.

#### Worked example — input

```json
{
  "keywords": ["logistics", "freight forwarding", "warehousing"],
  "countries": ["DE", "HU"],
  "published_after": "2026-01-01",
  "mode": "full",
  "max_items": 20
}
````

#### Worked example — output (real data, 2 of 20 items, fetched 2026-07-06)

```json
[
  {
    "tender_id": "464044-2026",
    "title": "Germany – Storage and warehousing services – Logistikdienstleistung Hilfsmittelversorgung",
    "buyer": "BG Klinikum Hamburg gGmbH",
    "country": ["DE"],
    "cpv": ["63120000", "64110000", "33141000", "33140000"],
    "deadline": "2026-07-13",
    "value_estimate": null,
    "currency": null,
    "url": "https://ted.europa.eu/en/notice/464044-2026/html",
    "publication_date": "2026-07-06",
    "notice_type": "cn-standard"
  },
  {
    "tender_id": "442473-2026",
    "title": "Germany, Belgium – Water transport services – On-/offshore Cable Jointing Services & Offshore Cable Repair Logistic Services",
    "buyer": "50Hertz Transmission GmbH: Vertragsschließende Einheit / Auftraggeber (Contracting Entity) für Lots 1–5",
    "country": ["DE", "BE"],
    "cpv": ["60600000", "45314300", "50532400"],
    "deadline": null,
    "value_estimate": 110000000.0,
    "currency": "EUR",
    "url": "https://ted.europa.eu/en/notice/442473-2026/html",
    "publication_date": "2026-06-29",
    "notice_type": "cn-standard"
  }
]
```

`value_estimate`/`deadline` are `null` on plenty of real notices — TED doesn't require every field for every notice type (e.g. a contract award notice, `notice_type: "can-standard"`, has no submission deadline; not every buyer discloses an estimated value). This is expected, not a bug — see "Known limitations".

### Output schema

| Field | Type | Notes |
|---|---|---|
| `tender_id` | string | TED's own publication number, e.g. `"461933-2026"`. Globally unique; also the delta-mode dedup key. |
| `title` | string or `null` | Notice title (English; TED auto-translates into all 24 EU languages, so this is present for effectively every notice). |
| `buyer` | string or `null` | Contracting authority name. |
| `country` | array of strings | Buyer country/ies, ISO 3166-1 **alpha-2**. A list because joint-procurement notices can have buyers from multiple countries. |
| `cpv` | array of strings | CPV codes (main + additional), deduplicated. |
| `deadline` | string or `null` | Earliest tender-submission deadline across the notice's lots, `"YYYY-MM-DD"`. |
| `value_estimate` | number or `null` | Estimated value of the notice's **first lot only** — see "Known limitations". |
| `currency` | string or `null` | ISO 4217 currency for `value_estimate`. |
| `url` | string | Link to the full notice on `ted.europa.eu` (English UI). |
| `publication_date` | string or `null` | `"YYYY-MM-DD"`. |
| `notice_type` | string or `null` | TED's own code, e.g. `"cn-standard"` (contract notice), `"can-standard"` (contract award notice), `"pin-standard"` (prior information notice). |

### Delta mode

Set `"mode": "delta"` on a scheduled run to get only tenders not already returned by a previous run with the **exact same** `keywords`/`cpv_codes`/`countries`/`published_after`/`deadline_before` (changing `max_items` or `mode` itself doesn't count as a different search — only the filter fields do).

How it works: a named Key-Value store (`ted-tender-monitor-seen`) holds one "seen tender IDs" record per distinct filter combination, keyed by a stable hash of those filter fields. Each delta run loads that record, skips any matching tender already in it, charges/delivers only the rest, and then adds the newly-delivered tenders' IDs back into the record. **A tender dropped by a budget stop (`ACTOR_MAX_TOTAL_CHARGE_USD`) is never marked "seen"** — it was never paid for or delivered, so it's offered again on the next run. The seen-set is bounded (pruned past 400 days old relative to its own newest entry, and hard-capped at 50,000 IDs) so it can't grow forever across months of scheduled runs.

**0 new tenders in delta mode is a normal, expected result** — most days, nothing new matches a narrow saved search. This actor logs an explicit `INFO` line ("Delta mode: 0 new tenders since last run (...)") and sets that as the run's status message, rather than the `WARNING` that `full` mode uses for its own "valid search, genuinely 0 matches" case (see "Error messages"). `full` mode runs never read or write the delta store at all, so alternating `full` and `delta` runs on the same search can't corrupt the delta baseline.

Verified locally: running the same delta-mode input twice in a row returned 15 real tenders on the first run and exactly 0 on the second, with the `INFO`-not-`WARNING` message, and the Key-Value store persisting the 15 tender IDs between runs.

### Pricing (pay-per-event)

| Event | Price | When it's charged |
|---|---|---|
| `tender-result` | $0.005 | Once per returned tender. In `delta` mode, only tenders not already returned by a previous run with the same search are charged. |

Plus Apify's own `apify-actor-start` synthetic event (first 5 seconds of compute free, platform-managed).

**Examples:** `full` mode, 20 matching tenders → `20 × $0.005 = $0.10`. `delta` mode on a daily schedule with typically 2–3 genuinely new tenders/day → `~$0.01–0.015`/day; a quiet day with 0 new tenders costs $0.00.

If a run's cost would exceed the `Max total charge USD` you set for it, the actor stops producing further tenders at exactly that point — every delivered tender was paid for, and nothing paid-for is ever dropped. Verified locally (`ACTOR_TEST_PAY_PER_EVENT=1`): `$3` budget → 1 tender charged = 1 delivered; `$5` → 2 = 2; both stopped gracefully with exit code 0, no crash.

### Error messages

- **No input at all / no search criteria:** explains the minimal valid input — at least one of `keywords`/`cpv_codes`/`countries`.
- **Dates alone, no other criteria:** *"'published\_after'/'deadline\_before' alone are not enough -- they narrow a search, they don't define one."*
- **Unrecognized country code:** *"'countries' entry 'ZZ' is not a recognized ISO 3166-1 alpha-2 country code..."* — also rejects alpha-3 codes (e.g. `"DEU"`) since this input field is alpha-2 by convention with the rest of this portfolio.
- **Malformed CPV code:** explains the required 2/4/6/8-digit shape with worked examples.
- **Keyword containing `"` or `\`:** rejected with a suggested fix (these characters can't appear in a TED full-text search term as constructed by this actor).
- **Malformed date / `published_after` after `deadline_before` / unknown `mode` / `max_items` out of range:** each rejected with the exact rule and an example fix.
- **0 tenders with otherwise valid input, `full` mode:** the run still succeeds (exit 0), but the log carries an explicit `WARNING: 0 results produced despite valid input (...)` line and the run's status message says so — never a silent "nothing happened."
- **0 tenders in `delta` mode:** explicit `INFO`, not `WARNING` — this is the expected steady state, not a problem. See "Delta mode".
- **TED API unreachable:** logged as an `ERROR` with the underlying cause; the run still completes (0 tenders, same as above) rather than crashing outright.

### TED API discoveries (undocumented outside this actor's code comments)

Recorded here because there is no user-facing grammar/field reference for TED's Search API v3 beyond its interactive [Expert Search](https://ted.europa.eu/en/search/expert-search) page — these were found by hitting the API directly and reading its own error messages (2026-07-06):

- **No API key needed.** `POST https://api.ted.europa.eu/v3/notices/search` works fully unauthenticated; no rate-limit headers were observed.
- **POST only** — a GET on the same path returns HTTP 405. The full (otherwise unlinked) OpenAPI spec is at `https://api.ted.europa.eu/api-v3.yaml`.
- **Expert-query dates are `YYYYMMDD`**, not ISO-8601 (confirmed via the server's own format-error message).
- **`buyer-country` takes ISO 3166-1 alpha-3** (`"DEU"`, not `"DE"`) — this actor's `countries` input stays alpha-2 for consistency with the rest of the portfolio and converts internally (`src/countries.py`).
- **`estimated-value-lot` is declared as `number` in TED's own OpenAPI spec but is actually returned as a numeric string** (e.g. `"110000000"`) — this actor coerces it to a float. Its companion array `estimated-value-cur-lot` isn't even guaranteed to be the same length (observed: 6 values, 1 shared currency).
- **Notice titles are auto-translated into all 24 EU languages** regardless of the notice's original language — the English version was present on every notice fetched during development, including ones from non-EU buyers (e.g. a Kazakhstan buyer).

### Known limitations (documented, not hidden)

- **`value_estimate`/`currency` reflect the first lot only.** A multi-lot tender's lots can have different estimated values and even different currencies — summing them would silently mix currencies or misrepresent the tender. The full per-lot breakdown is always one click away at `url`.
- **`deadline` is the earliest across all lots**, not necessarily every lot's deadline (most multi-lot tenders share one deadline anyway).
- **Delta mode's "seen" tracking is per exact filter combination.** Changing `keywords`/`cpv_codes`/`countries`/dates starts a fresh dedup baseline for that new combination (by design — it's a different saved search) rather than trying to guess overlap with a previous one.
- **`max_items` is capped at 500 per run** — TED's own Search API supports far more via pagination (up to 15,000 retrievable notices per query in the default pagination mode), but this actor stays well under that ceiling to keep runs fast and costs predictable; there's no scroll/iteration-mode support (not needed at this ceiling).

### Data source (public, no scraping)

TED (Tenders Electronic Daily) Search API v3, the European Union's official public procurement notice portal: `https://api.ted.europa.eu/v3/notices/search`. Public, unauthenticated, official EU data — the same API TED's own [Expert Search](https://ted.europa.eu/en/search/expert-search) page uses.

### Example use cases (logistics & freight, this actor's niche)

- **Freight forwarders / 3PLs**: watch for new road/rail/sea freight tenders (`cpv_codes: ["60", "63"]`) across the countries you operate in, on a daily `delta` schedule.
- **Warehousing operators**: `keywords: ["warehousing", "storage and distribution"]` to catch contract notices for third-party logistics/fulfillment contracts.
- **Bid/tender teams at logistics companies**: combine `countries` (your target markets) with `deadline_before` to get a rolling shortlist of tenders still open for bidding, sorted newest-first.
- **Consultancies tracking a client's procurement pipeline**: a `full`-mode run against a client's buyer-country + relevant CPV codes as a standing research query.

# Actor input Schema

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

Full-text search terms matched against the notice (title, description, etc.). Multiple keywords are OR'ed together (any match). Example: \["logistics", "freight forwarding"]. Cannot contain '"' or '\\' characters.

## `cpv_codes` (type: `array`):

Common Procurement Vocabulary codes to filter by: 2, 4, 6, or 8 digits (chapter/group/class/full code), e.g. "60" (transport services), "6024" (freight transport by road), "63120000" (storage and warehousing services). The official check-digit suffix ("-8") is accepted but ignored.

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

ISO 3166-1 alpha-2 codes for the contracting authority's (buyer's) country, e.g. "DE" (Germany), "HU" (Hungary). Not the notice's publication language. Defaults to \["DE", "HU"].

## `published_after` (type: `string`):

Only return notices published on or after this date ("YYYY-MM-DD"). Prefilled to a fixed, deliberately wide date (not a "today minus N days" relative window, which a static schema default can't express) so the default Run always returns results, however long after this actor was built it's run.

## `deadline_before` (type: `string`):

Only return notices whose tender-submission deadline is on or before this date ("YYYY-MM-DD"). Optional — omit to not filter by deadline (this also returns notices with no submission deadline at all, e.g. award notices).

## `mode` (type: `string`):

"full" returns every tender matching the search on every run (default). "delta" returns only tenders NOT already returned by a previous run with the exact same keywords/cpv\_codes/countries/date filters — intended for scheduled/recurring runs to get an "only what's new" feed. Delta mode's seen-tender tracking is stored per exact filter combination, keyed off those filter fields only (not 'mode' or 'max\_items').

## `max_items` (type: `integer`):

Maximum number of tenders to return (and charge for) in this run. 1-500.

## Actor input object example

```json
{
  "keywords": [
    "logistics",
    "freight forwarding"
  ],
  "cpv_codes": [
    "6024",
    "63120000"
  ],
  "countries": [
    "DE",
    "HU"
  ],
  "published_after": "2026-01-01",
  "deadline_before": "2026-12-31",
  "mode": "full",
  "max_items": 20
}
```

# Actor output Schema

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

Matching EU procurement notices, newest-published-first, stored in the run's default dataset.

# 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": [
        "logistics"
    ],
    "countries": [
        "DE",
        "HU"
    ],
    "published_after": "2026-01-01",
    "mode": "full",
    "max_items": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("westerly_breaker/ted-tender-monitor").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": ["logistics"],
    "countries": [
        "DE",
        "HU",
    ],
    "published_after": "2026-01-01",
    "mode": "full",
    "max_items": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("westerly_breaker/ted-tender-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": [
    "logistics"
  ],
  "countries": [
    "DE",
    "HU"
  ],
  "published_after": "2026-01-01",
  "mode": "full",
  "max_items": 20
}' |
apify call westerly_breaker/ted-tender-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=westerly_breaker/ted-tender-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "TED EU Tender Monitor — Search & Delta-Track Tenders",
        "description": "Search EU public procurement notices (TED) by keyword, CPV code, country and date as clean JSON, with a delta mode returning only new tenders per run. Built for logistics/freight bid teams. No API key needed.",
        "version": "0.1",
        "x-build-id": "CmsvK16eAS1crgERg"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/westerly_breaker~ted-tender-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-westerly_breaker-ted-tender-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/westerly_breaker~ted-tender-monitor/runs": {
            "post": {
                "operationId": "runs-sync-westerly_breaker-ted-tender-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/westerly_breaker~ted-tender-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-westerly_breaker-ted-tender-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "keywords": {
                        "title": "Keywords",
                        "type": "array",
                        "description": "Full-text search terms matched against the notice (title, description, etc.). Multiple keywords are OR'ed together (any match). Example: [\"logistics\", \"freight forwarding\"]. Cannot contain '\"' or '\\\\' characters.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "cpv_codes": {
                        "title": "CPV codes",
                        "type": "array",
                        "description": "Common Procurement Vocabulary codes to filter by: 2, 4, 6, or 8 digits (chapter/group/class/full code), e.g. \"60\" (transport services), \"6024\" (freight transport by road), \"63120000\" (storage and warehousing services). The official check-digit suffix (\"-8\") is accepted but ignored.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "countries": {
                        "title": "Buyer countries",
                        "type": "array",
                        "description": "ISO 3166-1 alpha-2 codes for the contracting authority's (buyer's) country, e.g. \"DE\" (Germany), \"HU\" (Hungary). Not the notice's publication language. Defaults to [\"DE\", \"HU\"].",
                        "items": {
                            "type": "string"
                        }
                    },
                    "published_after": {
                        "title": "Published after",
                        "type": "string",
                        "description": "Only return notices published on or after this date (\"YYYY-MM-DD\"). Prefilled to a fixed, deliberately wide date (not a \"today minus N days\" relative window, which a static schema default can't express) so the default Run always returns results, however long after this actor was built it's run."
                    },
                    "deadline_before": {
                        "title": "Deadline before",
                        "type": "string",
                        "description": "Only return notices whose tender-submission deadline is on or before this date (\"YYYY-MM-DD\"). Optional — omit to not filter by deadline (this also returns notices with no submission deadline at all, e.g. award notices)."
                    },
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "full",
                            "delta"
                        ],
                        "type": "string",
                        "description": "\"full\" returns every tender matching the search on every run (default). \"delta\" returns only tenders NOT already returned by a previous run with the exact same keywords/cpv_codes/countries/date filters — intended for scheduled/recurring runs to get an \"only what's new\" feed. Delta mode's seen-tender tracking is stored per exact filter combination, keyed off those filter fields only (not 'mode' or 'max_items').",
                        "default": "full"
                    },
                    "max_items": {
                        "title": "Max items",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Maximum number of tenders to return (and charge for) in this run. 1-500.",
                        "default": 20
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
