# UK Tenders API: Find a Tender + Contracts Finder (`adamhaleworks/uk-tenders-find-a-tender-contracts-finder`) Actor

UK public tenders and contract awards from Find a Tender and Contracts Finder in one feed. Filter by keyword, CPV, region, value, open deadline and SME suitability. Deadlines, values, lots, award criteria and suppliers (companies only). Only-new mode for daily tender alerts.

- **URL**: https://apify.com/adamhaleworks/uk-tenders-find-a-tender-contracts-finder.md
- **Developed by:** [Adam Hale](https://apify.com/adamhaleworks) (community)
- **Categories:** Business, Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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 Tenders API: Find a Tender + Contracts Finder search and tender alerts, with deadlines, values and winners

Search **UK public sector tenders and contract awards** from both official portals at once: **Find a Tender** (FTS, the main UK portal under the Procurement Act 2023) and **Contracts Finder** (lower-value English contracts). Each notice becomes one clean row:

- **Title, buyer** (name, type, town, postcode, region) and a link to the official notice
- **Deadline** for tenders or requests to participate, with days left and an open/closed flag
- **Estimated value** (excl. and incl. VAT) and **awarded value**
- **Winning suppliers** of contract awards (company names, Companies House/PPON IDs, SME flag)
- **CPV codes** with descriptions, delivery regions (ITL/NUTS codes and names), procedure, legal basis, lots and award criteria
- **SME and VCSE suitability**, contract start and end dates, document links

Filter by **keyword, CPV code, region, value, buyer, notice type and open deadline**. Then turn on **Only new notices since the last run** and schedule a daily run to get your own **UK tender alert**. Tender-alert subscriptions cost £25–100+ a month; this costs cents.

It reads the portals' official OCDS APIs, so there is no scraping, no browser and no proxy. **Free while in launch; planned pay-per-event price: $1.50 per 1,000 notices.**

### What can I use it for?

- **Daily tender alerts for your bid team.** New UK tenders matching your sector, region and size, every morning, by email, Slack, Google Sheets or webhook.
- **Competitor and market analysis.** Who wins which public contracts, from which buyers, at what value. Award notices from both portals are included.
- **Pipeline planning.** Pipeline, preliminary market engagement and planned procurement notices (UK1–UK3) show what buyers intend to buy months in advance.
- **CRM and BI feeds.** Send clean JSON or CSV to your CRM, Airtable or data warehouse through Apify integrations or the API.
- **Research and journalism.** Public spending by sector, region, procedure type or buyer.

### What data does it return?

| Field | Example |
|---|---|
| `noticeId`, `noticeUrl`, `source` | `093436-2026`, link to the notice, `Find a Tender` or `Contracts Finder` |
| `stage`, `noticeType`, `noticeTypeLabel`, `isUpdate` | `tender`, `UK4`, `Tender notice` |
| `title`, `description`, `procurementReference` | `Commercial Asset Management System` |
| `publishedAt`, `publishedDate` | `2026-10-02T14:01:41Z` |
| `buyerName`, `buyerType`, `buyerTown`, `buyerPostcode`, `buyerRegion`, `buyerWebsite`, `buyerId` | `Oxford City Council`, `Public authority - sub-central government`, `Oxford`, `OX1 1BX`, `UKJ14` |
| `cpvMain`, `cpvMainDescription`, `cpvCodes` | `48100000`, `Industry specific software package` |
| `deliveryRegions`, `deliveryRegionNames`, `nationwide` | `["UKJ14"]`, `["South East"]` |
| `estimatedValue`, `estimatedValueInclVat`, `estimatedValueCurrency` | `1800000`, `2160000`, `GBP` |
| `deadline`, `deadlineType`, `daysUntilDeadline`, `isOpen`, `enquiryDeadline` | `2026-11-05T12:00:00Z`, `tenders`, `32`, `true` |
| `contractStart`, `contractEnd` | `2027-06-01`, `2032-05-31` |
| `procurementMethod`, `procurementMethodDetails`, `legalBasis`, `aboveThreshold` | `open`, `Open procedure`, `Procurement Act 2023`, `true` |
| `suitableForSme`, `suitableForVcse`, `lotCount`, `lots[]` | lot title, value, CPV, award criteria, SME suitability |
| `awardedValue`, `awardDate`, `supplierNames`, `suppliers[]` | `46000000.09`, `2026-09-30`, `["Softcat PLC", …]` |
| `documentUrls`, `submissionDetails` | Link to the buyer's e-tendering portal |
| `matchedKeywords` | Which of your keywords matched |

#### Example output

A call for tenders from a real run on 2026-10-04 (shortened):

```json
{
  "noticeId": "093436-2026",
  "source": "Find a Tender",
  "noticeUrl": "https://www.find-tender.service.gov.uk/Notice/093436-2026",
  "noticeTypeLabel": "Tender notice",
  "publishedDate": "2026-10-02",
  "title": "Commercial Asset Management System",
  "buyerName": "Oxford City Council",
  "buyerType": "Public authority - sub-central government",
  "buyerTown": "Oxford",
  "procurementMethodDetails": "Open procedure",
  "legalBasis": "Procurement Act 2023",
  "cpvMain": "48100000",
  "cpvMainDescription": "Industry specific software package",
  "deliveryRegionNames": ["South East"],
  "estimatedValue": 1800000.0,
  "estimatedValueInclVat": 2160000.0,
  "deadline": "2026-11-05T12:00:00Z",
  "deadlineType": "tenders",
  "daysUntilDeadline": 32,
  "isOpen": true,
  "contractStart": "2027-06-01",
  "contractEnd": "2032-05-31",
  "submissionDetails": "https://in-tendhost.co.uk/oxfordcc/aspx/Home",
  "matchedKeywords": ["software"]
}
```

A contract award from the same run (shortened, 16 suppliers):

```json
{
  "noticeId": "093427-2026",
  "noticeTypeLabel": "Contract award notice",
  "title": "Corporate Software & Related Products and Services - ITT",
  "buyerName": "Crescent Purchasing Consortium Limited",
  "nationwide": true,
  "awardedValue": 46000000.09,
  "awardDate": "2026-09-30",
  "contractStart": "2026-10-19",
  "contractEnd": "2028-10-18",
  "lotCount": 10,
  "supplierNames": ["Xledger UK ltd", "Advanced Business Solutions", "ION Industries Ltd", "Softcat PLC", "…"],
  "suppliers": [{"name": "Softcat PLC", "id": "GB-PPON-PZRT-9169-TVMT", "town": "Marlow", "country": "GB", "scale": "large", "vcse": false}]
}
```

The Output tab has two ready-made views, **Tenders** and **Contract awards**. Export as CSV, Excel or JSON, or fetch the results through the API.

### How much does it cost?

**Free while in launch.** The actor charges no fee of its own right now; you pay only the Apify platform usage of your runs (the free Apify plan includes $5 of usage a month). The pay-per-event price below is planned and applies only once it is switched on; Apify notifies existing users before a price change takes effect.

| Event | Planned price |
|---|---|
| Notice output | **$0.0015** (= $1.50 per 1,000 notices) |

- Notices removed by your filters, older versions of the same notice and notices already delivered in earlier runs ("Only new" mode) are **not charged**.
- **Alert example** (at the planned price): our test alert (tenders and planning notices in London and the South East above £50,000) found 105 notices in the last 3 days on its first run ($0.16). The next run found 0 new notices ($0.00). After simulating 3 new notices, the run after that would cost $0.0045.
- **Cost cap:** once pricing is on, set **Maximum cost per run** and the actor stops cleanly when it reaches it.

For comparison (Apify Store, checked 2026-10-04): other UK tender actors charge $2–$15 per 1,000 notices, several add a per-run start fee, and one charges $0.10 per notice. UK tender-alert subscriptions cost £25–100+ a month.

### How to use it

1. Set your filters: keywords, notice types, CPV codes, regions, value range, buyer names or "Only open tenders". All filters are optional and combined with AND. Several values inside one filter are combined with OR.
2. Choose the period: **Published in the last N days** (default 3), or exact dates.
3. Click **Start**. Results are sorted newest first.

#### Daily tender alert

```json
{
  "keywords": ["software", "cyber security", "cloud*"],
  "noticeTypes": ["tender"],
  "onlyOpen": true,
  "regions": ["London", "South East"],
  "minValueGbp": 50000,
  "publishedWithinDays": 2,
  "onlyNew": true
}
```

Create a schedule (for example every weekday at 08:00) with this input and connect an integration (email, Slack, Google Sheets, webhook) to the run's dataset. Each run returns only notices you haven't received before. The 2-day window means a missed run never loses notices.

#### Who won IT contracts in the last 3 days?

```json
{
  "noticeTypes": ["award"],
  "cpvCodes": ["72", "48"],
  "publishedWithinDays": 3,
  "maxItems": 1000
}
```

#### API example

```bash
curl -X POST "https://api.apify.com/v2/acts/adamhaleworks~uk-tenders-find-a-tender-contracts-finder/run-sync-get-dataset-items?token=<TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"keywords": ["software"], "noticeTypes": ["tender"], "onlyOpen": true}'
```

#### Useful CPV codes and regions

CPV: `72` IT services · `48` software packages · `45` construction work · `79` business services · `85` health and social care · `90` waste and cleaning · `71` architecture and engineering · `33` medical equipment · `34` transport equipment · `80` education and training. A short code includes every code below it.

Regions: `London`, `South East`, `South West`, `East of England`, `East Midlands`, `West Midlands`, `North East`, `North West`, `Yorkshire and the Humber`, `Wales`, `Scotland`, `Northern Ireland`, `England`, or ITL/NUTS codes such as `UKI`, `TLJ` or `UKM7`. Nationwide notices (delivered across the UK) are included by default.

### How it works

- **Data sources.** The official OCDS APIs of [Find a Tender](https://www.find-tender.service.gov.uk/apidocumentation) and [Contracts Finder](https://www.contractsfinder.service.gov.uk/apidocumentation). No key is needed, and both publish under the Open Government Licence v3.0. The two portals barely overlap (2 of 197 Contracts Finder notices on a test day were also on Find a Tender), so reading both gives the full picture.
- **Filtering.** The APIs only filter by date, so the actor reads every notice in your date window and applies your filters itself. Keywords match whole words in the title, description, main CPV description and lot titles (`cloud*` matches cloud and cloud-based). Set **Search keywords in** to **Title only** for stricter matching.
- **Rate limits.** Find a Tender allows about 12 requests (1,200 notices) per 2 minutes. The actor stays under that, so up to 3 days of notices are read in about 10 seconds, and a week takes about 4 minutes. If a portal asks it to slow down (for example when you start two runs within a minute or two), it waits the 2 minutes the portal asks for and continues. Nothing is lost.
- **One row per notice.** When a tender has been updated, only the latest version is returned by default (turn off **Only the latest version of each notice** to get every version).
- **Only new.** The notices already delivered for a search are stored in a named key-value store in your account. A different search keeps a separate memory.
- **Reliability.** If one portal is down, notices from the other are still delivered and the status message says what is missing. A migrated run continues without delivering or charging notices twice.

### Limitations

- Notices are as published by buyers. Some have no value, a value only per lot, or a region only for the buyer. The region filter then falls back to the buyer's region.
- Contracts Finder mostly carries awards and lower-value English contracts. Scottish (Public Contracts Scotland), Welsh (Sell2Wales) and Northern Irish portals are not read, but their above-threshold notices also appear on Find a Tender.
- Long date windows are slow because of Find a Tender's rate limit: about 6 minutes per 10 days.
- Contact persons, email addresses and phone numbers are never included. Descriptions are scanned to remove email addresses and phone numbers.
- **Supplier names:** a supplier can be a sole trader whose business name is a person's name. To avoid outputting personal data, a supplier's name is shown only when it contains a company or organisation marker (Ltd, LLP, PLC, CIC, Council, Trust, University, Solutions, and so on). Otherwise the row says `"nameWithheld": true` and keeps the country and SME flag. In our 3-day IT awards test, 8 of 153 supplier entries (5%) were withheld.

### Is it legal?

Both portals are official UK government services, and their data is published under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/), which allows commercial reuse with attribution: *Contains public sector information licensed under the Open Government Licence v3.0.* This actor is not affiliated with the Cabinet Office or Crown Commercial Service. It outputs organisations, not people. You are responsible for using the data in line with the laws that apply to you.

### FAQ

**Why do I get fewer results than on the portal?** "Only open tenders" drops notices whose deadline has passed, value filters drop notices without a published value, and "Only the latest version of each notice" collapses updates into one row.

**Why is a tender's deadline empty?** Some procedures (for example the competitive flexible procedure's first stage) only publish a deadline for requests to participate. That deadline is returned with `deadlineType: "requestsToParticipate"`. Some notices have no deadline at all.

**Does it include Scottish and Welsh tenders?** Above-threshold notices from all four nations are on Find a Tender and included. Smaller Scottish and Welsh contracts that only appear on Public Contracts Scotland or Sell2Wales are not.

**Something is wrong or missing?** Open an issue on the actor's Issues tab and include the notice ID.

***

Author: Adam Hale

# Actor input Schema

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

Notices matching ANY of these words or phrases (whole words, case-insensitive) in the title, description or lot titles. A trailing \* matches word endings, for example cyber\* matches cybersecurity. Empty = no keyword filter.

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

Tender = open opportunities to bid (UK4 tender notices and their updates). Planning = pipeline, market engagement and planned procurement notices. Award = contract awards, contract details and transparency (direct award) notices. Contract = contract changes and terminations. Cancellation = procurements cancelled. Empty = all types.

## `onlyOpen` (type: `boolean`):

Keep only notices whose deadline for tenders or requests to participate is still in the future.

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

Common Procurement Vocabulary codes. A short code covers everything below it: 72 = all IT services, 48 = software packages, 45 = construction work, 79 = business services, 85 = health and social care, 90 = waste and cleaning.

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

Where the contract is delivered: names (London, South East, Scotland, Wales, Northern Ireland, England, …) or ITL/NUTS codes (UKI, TLI, UKM7). Falls back to the buyer's region when the notice names no delivery region.

## `publishedWithinDays` (type: `integer`):

Only notices published in the last N days. Ignored when "Published from" is set. Up to 3 days finishes in under a minute. Find a Tender serves about 1,100 notices per 2 minutes, so longer windows take about 6 minutes per 10 days. For daily alerts use 2 days with "Only new notices".

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

Keep only notices with an estimated (or awarded) value of at least this amount. Notices without a published GBP value are dropped when this is set.

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

Keep only notices with an estimated (or awarded) value of at most this amount. Notices without a published GBP value are dropped when this is set.

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

Keep only notices where the buyer marked the contract (or a lot) as suitable for small and medium-sized enterprises.

## `vcseSuitableOnly` (type: `boolean`):

Keep only notices marked as suitable for voluntary, community and social enterprises.

## `buyerNames` (type: `array`):

Keep only notices whose buyer name contains any of these texts, for example NHS, Council, Ministry of Defence.

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

Drop notices that contain any of these words or phrases.

## `searchIn` (type: `string`):

Title and description (incl. lot titles and the main CPV description), or the title only.

## `includeNationwide` (type: `boolean`):

With a region filter, also keep notices delivered across the whole UK.

## `includeUpdates` (type: `boolean`):

Keep update notices (for example a tender notice with a changed deadline). They are marked isUpdate = true.

## `latestVersionOnly` (type: `boolean`):

Find a Tender publishes every update as a new notice. When on, a run outputs only the newest notice per procurement and notice type (older versions in the window are skipped and not charged).

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

Find a Tender carries all Procurement Act 2023 notices (above and below threshold) since 24 February 2025. Contracts Finder still carries older procurements and call-offs. Empty = both.

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

Start date, for example 2026-09-01. Overrides "Published in the last N days".

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

End date (inclusive), for example 2026-09-30.

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

Remember which notices were already output for this search and skip them next time. Schedule the actor daily with a window of 2-3 days to get tender alerts. The first run outputs all matches in the date window.

## `stateStoreName` (type: `string`):

Named key-value store that remembers output notices for "Only new" mode. Each different search keeps its own memory inside it.

## `includeDescription` (type: `boolean`):

Add the procurement description (up to 4,000 characters) and submission details. E-mail addresses and phone numbers are removed.

## `includeLots` (type: `boolean`):

Add a list of lots with title, value, SME suitability, contract dates and award criteria with weights.

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

Stop after this many notices. 0 = up to 200,000.

## `requestTimeoutSecs` (type: `integer`):

Timeout for one API request.

## `maxRetries` (type: `integer`):

Retries for network errors, rate limits and 5xx responses. Rate-limit waits follow the API's Retry-After header (2 minutes on Find a Tender, 5 minutes on Contracts Finder).

## Actor input object example

```json
{
  "keywords": [
    "software",
    "cyber security",
    "cloud*"
  ],
  "noticeTypes": [
    "tender"
  ],
  "onlyOpen": false,
  "cpvCodes": [
    "72",
    "48000000"
  ],
  "regions": [
    "London",
    "South East"
  ],
  "publishedWithinDays": 3,
  "smeSuitableOnly": false,
  "vcseSuitableOnly": false,
  "searchIn": "titleAndDescription",
  "includeNationwide": true,
  "includeUpdates": true,
  "latestVersionOnly": true,
  "onlyNew": false,
  "stateStoreName": "uk-tenders-state",
  "includeDescription": true,
  "includeLots": true,
  "maxItems": 100,
  "requestTimeoutSecs": 60,
  "maxRetries": 4
}
```

# Actor output Schema

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

Dataset items, one per notice. Views: tenders, contract awards.

## `summary` (type: `string`):

SUMMARY record in the default key-value store: notices scanned and output, per-source counts and errors, date window, only-new state, stop reason and rate limiting.

# 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",
        "cyber security"
    ],
    "noticeTypes": [
        "tender"
    ],
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("adamhaleworks/uk-tenders-find-a-tender-contracts-finder").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",
        "cyber security",
    ],
    "noticeTypes": ["tender"],
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("adamhaleworks/uk-tenders-find-a-tender-contracts-finder").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",
    "cyber security"
  ],
  "noticeTypes": [
    "tender"
  ],
  "maxItems": 100
}' |
apify call adamhaleworks/uk-tenders-find-a-tender-contracts-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,adamhaleworks/uk-tenders-find-a-tender-contracts-finder"
        }
    }
}
```

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/mTItQlsmybReJbBC9/builds/dSgNEQiQvrdvKlsTX/openapi.json
