# Public Tenders UK & EU: Find a Tender, Contracts Finder, TED (`lineagersiui/public-tender-feed`) Actor

Public procurement feed for UK and EU tenders: new opportunity notices from official Find a Tender, Contracts Finder and TED APIs in one normalised schema. Filter by keyword, CPV, country, value and date; 'only new' skips seen notices. No awards. Contact details removed (best effort). Free demo.

- **URL**: https://apify.com/lineagersiui/public-tender-feed.md
- **Developed by:** [Lineage RSIUI](https://apify.com/lineagersiui) (community)
- **Categories:** Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 notice returneds

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

## Public Tenders UK & EU: Find a Tender, Contracts Finder, TED

**One feed of new public contract opportunities from the UK and the EU.** It reads the official Find a Tender and Contracts Finder APIs (UK) and the TED Search API (EU). Results come back in one normalised schema, with UK notices de-duplicated across the two portals. Filter by keyword, CPV code, country, value and publication date. With **only new**, each run returns just the notices you haven't seen.

### Use this Actor when…

Use this Actor when:

- you bid for public contracts, or advise companies that do, and want new UK and EU opportunities in one place;
- you want a scheduled "what's new since yesterday" feed (`onlyNew`) for a set of keywords, CPV codes or countries, to send on to a spreadsheet, CRM, Slack or e-mail;
- you need machine-readable notices: one dataset item per notice, with the same fields for every source.

Inputs: `keywords`, `cpvCodes`, `countries` (ISO codes such as GB, DE, FR), `publishedSince` (default 7 days), `minValue` / `maxValue`, `includeNoValue`, `includeClosed`, `onlyNew`, `maxNotices` (default 200, at most 1,000) and `sources` (`fts`, `cf`, `ted`).

Don't use it for: contract award notices or awarded suppliers (not included in this version), buyer contact details (left out on purpose), tender documents, or any portal other than the three official sources.

### Try it free first

Run it with empty keywords, CPV codes and countries. A **free demo** returns up to 10 notices published in the last 24 hours (TED gives publication days only, so its demo notices can be from yesterday). Every demo item has `demo: true`, and the demo isn't billed.

### Public tenders it covers

- **UK, above threshold:** Find a Tender (`fts`).
- **UK, below threshold:** Contracts Finder (`cf`).
- **EU:** TED (`ted`), with buyer countries as ISO codes (for example DE, FR, IT).

Opportunity notices only: award and result notices are not included. Filter by keyword, CPV code or prefix (for example `72` for IT services), country, value and publication date.

### Output: tender notices in one schema

One dataset item per notice:

- `source`: `find-a-tender`, `contracts-finder` or `ted`;
- `noticeId` and `ocid`: OCID for the UK sources;
- `title` and `description`: description shortened to 2,000 characters;
- `buyerName`, the organisation only, and `country`, an ISO code;
- `cpvCodes`;
- `valueAmount` and `valueCurrency`, the estimated value where the notice publishes one;
- `publishedAt`, `deadline` and `procedureType`;
- `noticeUrl`, a link to the official notice;
- `licence`, the attribution for that source.

A `SUMMARY` record holds the counts, each source's status and the billing totals.

### How the public procurement feed works

1. **Three official APIs, nothing else.** Find a Tender (OCDS release packages), Contracts Finder (OCDS notice search) and TED (Search API, anonymous access). Opportunity notices only: award and result notices are left out.
2. **Filters.** TED filters by keyword, CPV and country on its own servers. The UK APIs have no keyword search, so recent UK notices are read page by page and filtered by the Actor: up to 2,400 Find a Tender releases (24 pages, about the last 5 days at current volumes) and up to 1,000 Contracts Finder tender releases (10 pages) per run. When a cap ends the reading early, `SUMMARY.sourceStatus` shows `page_cap_reached` and older notices are not returned. Keywords are always checked against each returned title and description, for all three sources. A keyword that TED's search can't use, such as `C++`, is matched only locally. If none of your keywords can be used with TED, TED is skipped, and `SUMMARY.sourceStatus` says so.
3. **De-duplication.** UK notices are matched across the two portals by OCID, and otherwise by title, buyer and deadline. Within a run, each notice is returned and billed once. Without `onlyNew`, a later run can return, and bill, the same notice again.
4. **Only new (optional).** The Actor remembers which notices it has already returned for your filter set. It keeps them in a key-value store named `public-tender-feed-state` in your own Apify account, as short digests rather than notice text. The next run then skips those notices. Amendments to a notice that was already returned are not returned again under `onlyNew`.

### What it can't do

- **No completeness guarantee.** The feed holds what the official APIs return during the run, within the run's limits. Sources can be slow, limited or temporarily unavailable; `SUMMARY.sourceStatus` shows what happened for each source.
- **The official notice is the authentic version.** Fields are normalised and descriptions are shortened. For TED, the legally authentic text is the version published in the Official Journal (OJ S). Always check `noticeUrl` before you bid.
- **Awards are excluded.** This version covers opportunities only.
- **Contact details are removed on a best-effort basis.** Contact fields (names, e-mails, phones, addresses) are never read. In free text, e-mail addresses, phone numbers and common forms of contact names are replaced with `[removed]`, but a personal name can occasionally remain in a description. To report one, open an issue on the **Issues** tab and we'll remove it. Use the official notice to contact a buyer.
- Values are compared in each notice's own currency, without conversion. Many notices publish no value.

### Polite access to public services

- The Actor contacts only the three official API hosts, sends at most one request per second to TED and at most one every 10 seconds to Find a Tender and Contracts Finder (at most 24 and 10 per run respectively), and identifies itself with a clear user agent.
- If a service refuses or rate-limits a request (403, 429, or a "rate limit" message) or has a server error (5xx), the Actor stops using that service for the rest of the run, with one exception. After a rate limit (429 or a "rate limit" message) or "service unavailable" (503) that asks for a wait of up to 30 seconds, it waits and retries once. That retry can add one request beyond the per-source page cap.
- Each run is capped at 1,000 notices and about 9 minutes of fetching.

### Pricing

- **Pay per notice returned:** each notice written to your dataset is one `notice-returned` event. This is the only event this Actor charges.
- **Not billed:** the demo, duplicates removed by de-duplication, notices skipped as already seen (`onlyNew`), empty runs, failed sources and runs stopped for invalid input (for example, only unrecognised country codes).
- The price is shown on the Pricing tab. You can cap the maximum charge per run in Apify's run options.

### Attribution and licences

- Contains public sector information licensed under the Open Government Licence v3.0. Licence: https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/
- TED notices © European Union, 1998-2026, reused under the Commission reuse policy; normalised by this Actor. Source: https://ted.europa.eu

Each item's `licence` field repeats the attribution for its source. No logos or emblems of TED, the UK Government or Crown Commercial Service are used.

### Support

Open an issue on this Actor's **Issues** tab.

### About

- **Independent:** made by an independent developer. Unofficial; not affiliated with or endorsed by Apify. Also not affiliated with or endorsed by the UK Government, Crown Commercial Service or the EU Publications Office.
- **Built with AI:** built and maintained with the help of AI tools, under the developer's direction.

# Actor input Schema

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

A notice matches if ANY keyword appears (case-insensitive) in its title or description, e.g. software, cleaning, solar. TED is also searched with its own full-text search; keywords it cannot use (e.g. C++) are matched only locally. Up to 20.

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

Common Procurement Vocabulary codes. Trailing zeros mean the whole branch: 72000000 (or 72) matches all IT services, 45233120 matches that code and its sub-codes. Up to 30.

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

Buyer countries as ISO 3166 two-letter codes: GB (or UK) for the UK sources; DE, FR, IE, NL, PL, IT, ES and other EU/EEA codes for TED. Empty means all countries.

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

Only notices published on or after this date: a date such as 2026-10-20, or a relative period such as 7 days, 2 weeks or 48 hours. Default 7 days; at most 90 days back.

## `minValue` (type: `integer`):

Only notices with an estimated value at or above this amount, in the notice's own currency (GBP for UK, usually EUR for TED; no currency conversion).

## `maxValue` (type: `integer`):

Only notices with an estimated value at or below this amount, in the notice's own currency.

## `includeNoValue` (type: `boolean`):

When a minimum or maximum value is set, notices that publish no value are left out unless this is on. Many notices publish no value.

## `includeClosed` (type: `boolean`):

Off by default: notices with a tender deadline in the past are left out.

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

Remembers which notices this exact filter set already returned (in a key-value store named public-tender-feed-state in your account) and returns only unseen ones. Notices skipped as already seen are not billed. Ideal for scheduled runs.

## `maxNotices` (type: `integer`):

Upper limit of notices returned (and billed) in one run. When the limit cuts the results, the sources share it in turn; the output is then sorted newest first. 1 to 1,000.

## `sources` (type: `array`):

Which official sources to query: fts (Find a Tender, UK above threshold), cf (Contracts Finder, UK below threshold), ted (EU). Empty means all three. Countries also select sources: GB queries only the UK sources; EU codes query only TED.

## Actor input object example

```json
{
  "publishedSince": "7 days",
  "includeNoValue": false,
  "includeClosed": false,
  "onlyNew": false,
  "maxNotices": 200
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "publishedSince": "7 days"
};

// Run the Actor and wait for it to finish
const run = await client.actor("lineagersiui/public-tender-feed").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 = { "publishedSince": "7 days" }

# Run the Actor and wait for it to finish
run = client.actor("lineagersiui/public-tender-feed").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 '{
  "publishedSince": "7 days"
}' |
apify call lineagersiui/public-tender-feed --silent --output-dataset

```

## MCP server setup

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

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/k3IXV1TgGcS7SKioG/builds/zNbBk6AU7IkBJUTon/openapi.json
