# UK Public Tenders - Contracts Finder + Find a Tender (`ennobling_spray/uk-public-tenders`) Actor

Daily-fresh UK government procurement notices: open tenders, pipeline notices and contract awards from Contracts Finder and Find a Tender, normalised into one clean schema with keyword, CPV, value, region and SME filters. Official data sources, no scraping fragility.

- **URL**: https://apify.com/ennobling_spray/uk-public-tenders.md
- **Developed by:** [Conor Wilson](https://apify.com/ennobling_spray) (community)
- **Categories:** Business, Lead generation, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 notices

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

## UK Public Tenders & Contract Awards

One feed for UK public-sector procurement: live tenders, pipeline (planning) notices and contract awards from **Contracts Finder** and **Find a Tender**, normalised into a single clean schema and filtered by keyword, CPV code, buyer, region, value and SME suitability.

Built on the two official open-data APIs, not on page scraping, so it does not break when a website is redesigned. Runs in seconds and costs a fraction of a penny per notice.

### Who this is for

- **Bid and sales teams** who want a daily list of new opportunities in their sector, pushed to a spreadsheet, CRM, Slack or email via Apify integrations.
- **Market and competitor analysts** tracking who is winning which contracts, at what value.
- **Journalists, researchers and civic-tech builders** who need bulk, structured procurement data without writing API code.
- **AI agents** that need a reliable tool for "find UK tenders about X" (works through Apify's MCP server).

### What you get

One row per notice:

| Field                                                                                                  | Example                                                         |
| ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- |
| `stage`                                                                                                | `tender`, `planning` or `award`                                 |
| `title`, `description`                                                                                 | Full text of the notice                                         |
| `buyerName`, `buyerType`, `buyerLocality`, `buyerPostcode`, `buyerEmail`, `buyerPhone`, `buyerWebsite` | The contracting authority and its published procurement contact |
| `cpvCodes`, `cpvDescriptions`                                                                          | All CPV classifications, e.g. `72000000` IT services            |
| `valueAmount`, `valueMin`, `valueMax`, `currency`                                                      | Estimated or awarded value                                      |
| `deadline`, `isOpen`                                                                                   | Submission deadline and whether it is still in the future       |
| `contractStart`, `contractEnd`                                                                         | Contract period                                                 |
| `deliveryRegions`                                                                                      | Where the work is delivered                                     |
| `smeSuitable`, `vcseSuitable`                                                                          | Buyer's suitability flags (Contracts Finder)                    |
| `suppliers`, `awardValue`, `awardDate`                                                                 | For awards: who won and for how much                            |
| `documents`                                                                                            | Links to tender packs and notice pages                          |
| `noticeUrl`, `noticeId`, `ocid`, `source`, `publishedDate`                                             | Identifiers and the human-readable notice page                  |

Set `includeRaw` to also get the complete original OCDS release.

### Quick start

New IT tenders in the last week, still open for bids:

```json
{
    "sources": ["contractsFinder", "findATender"],
    "stages": ["tender"],
    "daysBack": 7,
    "cpvPrefixes": ["72", "48"],
    "openOnly": true
}
```

Who won NHS contracts over £1m last month:

```json
{
    "stages": ["award"],
    "daysBack": 30,
    "buyerKeywords": ["NHS"],
    "minValueGbp": 1000000
}
```

Construction opportunities in Scotland suitable for SMEs:

```json
{
    "stages": ["tender"],
    "daysBack": 14,
    "cpvPrefixes": ["45"],
    "regions": ["Scotland", "UKM"],
    "smeSuitableOnly": true
}
```

### Input options

| Option                                         | Default      | Notes                                                                            |
| ---------------------------------------------- | ------------ | -------------------------------------------------------------------------------- |
| `sources`                                      | both         | `contractsFinder`, `findATender`                                                 |
| `stages`                                       | `["tender"]` | `tender`, `planning`, `award`                                                    |
| `daysBack`                                     | `7`          | Window ending today, unless explicit dates are given                             |
| `publishedFrom` / `publishedTo`                | -            | `YYYY-MM-DD`, inclusive                                                          |
| `keywords` / `excludeKeywords`                 | -            | Case-insensitive, matched on title + description; any keyword matches            |
| `cpvPrefixes`                                  | -            | e.g. `72` IT, `45` construction, `85` health, `80` education, `90` environmental |
| `buyerKeywords`                                | -            | Buyer name contains                                                              |
| `regions`                                      | -            | Matches delivery regions, buyer locality, postcode or NUTS code                  |
| `minValueGbp` / `maxValueGbp` / `requireValue` | -            | Value filters; unvalued notices kept unless `requireValue`                       |
| `smeSuitableOnly`                              | `false`      | Contracts Finder flag                                                            |
| `openOnly`                                     | `true`       | Drop tenders whose deadline has passed                                           |
| `includeRaw`                                   | `false`      | Attach the full OCDS release                                                     |
| `maxItems`                                     | `500`        | Hard cap on returned notices                                                     |

### Scheduling and integrations

Schedule the actor daily in Apify, then use an integration to push new rows to Google Sheets, Airtable, Slack, email, Make, Zapier or n8n. Use `ocid` to de-duplicate: one procurement keeps the same OCID across its tender, amendment and award notices.

### Data sources and licence

- Contracts Finder (Cabinet Office) OCDS API: notices from English and some UK-wide public bodies, typically above £12k (central government) or £30k (wider public sector).
- Find a Tender Service OCDS API: higher-value notices across the UK under the Procurement Act 2023, replacing OJEU/TED for the UK.

Both datasets are published under the Open Government Licence v3.0. Buyer contact details are the organisational procurement contacts the authorities publish for the purpose of receiving bids.

### Pricing

Pay per event: one event per notice returned, after filtering. Scanning and filtering are free; you only pay for what lands in your dataset. Set a maximum charge per run to cap spend.

# Actor input Schema

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

Contracts Finder covers lower-value notices from English (and some UK-wide) public bodies; Find a Tender covers higher-value notices under the Procurement Act 2023 across the UK.

## `stages` (type: `array`):

Which stage of the procurement lifecycle to return. 'Tender' = live opportunities you can bid for.

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

Fetch notices published or updated within this many days. Ignored if an explicit date range is set below.

## `publishedFrom` (type: `string`):

Optional explicit start date (inclusive). Overrides 'daysBack'.

## `publishedTo` (type: `string`):

Optional explicit end date (inclusive). Defaults to today.

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

Case-insensitive words or phrases matched against title and description. A notice is kept if ANY keyword matches. Leave empty for no keyword filter.

## `excludeKeywords` (type: `array`):

Drop notices whose title or description contains any of these.

## `cpvPrefixes` (type: `array`):

Keep notices whose CPV classification starts with any of these, e.g. 72 (IT services), 45 (construction), 85 (health). Leave empty for all.

## `buyerKeywords` (type: `array`):

Keep only notices where the buyer name contains any of these, e.g. 'NHS', 'Council', 'Ministry'.

## `regions` (type: `array`):

Keep notices whose delivery region, buyer locality, postcode area or NUTS code contains any of these, e.g. 'London', 'Scotland', 'UKI', 'M1'.

## `minValueGbp` (type: `integer`):

Keep notices with an estimated/awarded value of at least this. Notices without a stated value are kept unless 'requireValue' is on.

## `maxValueGbp` (type: `integer`):

Keep notices with a value at most this.

## `requireValue` (type: `boolean`):

Drop notices that do not state a value when a value filter is set.

## `smeSuitableOnly` (type: `boolean`):

Keep only notices the buyer flagged as suitable for small and medium enterprises (Contracts Finder field; Find a Tender notices are kept).

## `openOnly` (type: `boolean`):

For 'tender' stage notices, drop those whose submission deadline has already passed.

## `includeRaw` (type: `boolean`):

Attach the full original OCDS JSON to every item (larger output).

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

Stop after this many matching notices. Each returned notice is one billable event.

## Actor input object example

```json
{
  "sources": [
    "contractsFinder",
    "findATender"
  ],
  "stages": [
    "tender"
  ],
  "daysBack": 7,
  "keywords": [
    "software",
    "IT services"
  ],
  "excludeKeywords": [],
  "cpvPrefixes": [],
  "buyerKeywords": [],
  "regions": [],
  "requireValue": false,
  "smeSuitableOnly": false,
  "openOnly": true,
  "includeRaw": false,
  "maxItems": 500
}
```

# Actor output Schema

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

One row per procurement notice: stage, title, description, buyer and contact, CPV codes, value, deadline, contract period, suppliers and links.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": [
        "software",
        "IT services"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ennobling_spray/uk-public-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 = { "keywords": [
        "software",
        "IT services",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("ennobling_spray/uk-public-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 '{
  "keywords": [
    "software",
    "IT services"
  ]
}' |
apify call ennobling_spray/uk-public-tenders --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ennobling_spray/uk-public-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/tlMdybpsaw8WHQMSn/builds/jPXvJN7fEJG2mUpFj/openapi.json
