# UK Public Tenders: Find a Tender & Contracts Finder Alerts (`onibaku/uk-public-tenders`) Actor

Search UK public sector tenders, contract awards and planned procurements from Find a Tender and Contracts Finder. Filter by keyword, CPV code, region, buyer, value and deadline; get only new notices since the last run for scheduled tender alerts. Official OCDS APIs, flat output.

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

## Pricing

from $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

## UK Public Tenders & Contract Awards (Find a Tender + Contracts Finder)

Search **every UK public sector procurement notice** in one place: open **tenders**, **contract awards**, and
**pipeline and planned procurements**, from **Find a Tender** and **Contracts Finder**. Filter by keyword, CPV code,
region, buyer, value and bid deadline, and get one clean, flat row per notice: title, buyer, region, CPV codes,
estimated value, deadline, contract dates, SME suitability, who won it and for how much, and a link to the official
notice.

Run it on a schedule with `onlyNewNotices` and it becomes a **tender alert service**: each run returns only the
notices you haven't seen yet. Tender alert subscriptions cost £25 to £79 a month. A daily alert here typically costs
pennies.

It reads the government's **official OCDS APIs** (the open data feeds behind both services), so it's fast, cheap
and doesn't break when a website changes.

### What it's for

- **Bid writers and bid managers:** a daily feed of new opportunities in your clients' sectors and regions, with
  the deadline, value and documents link in every row.
- **Suppliers and SMEs:** catch tenders early. Pipeline (UK1), market engagement (UK2) and planned procurement (UK3)
  notices tell you what's coming months before the tender opens.
- **Sales and business development teams:** contract awards show who's buying what, from whom, at what price, and
  when the contract ends (so when it'll be re-tendered).
- **Market research and competitor tracking:** pull every award in a CPV division for a year and see which
  suppliers win.
- **AI agents:** one call answers "which NHS software tenders are open for bids in London right now?" (see
  MCP below).

### Input

| Field | What it does |
| --- | --- |
| `keywords` | Keep notices whose title or description contains any of these (at the start of a word), e.g. `software`, `facilities management`. |
| `excludeKeywords` | Drop notices containing any of these. |
| `cpvCodes` | CPV code prefixes: `72` (IT services), `48` (software packages), `4521` (building work), `85` (health and social care). `72000000` works too. |
| `regions` | Region names (`London`, `North West`, `Scotland`, `Wales`, `England`...) or NUTS/ITL codes (`UKI`, `UKD3`, `TLM`). Matched against the buyer's address and the delivery locations. |
| `includeUkWide` | In a region search, also keep notices delivered across the whole UK (on by default). |
| `buyerNames` | Buyer name contains any of these, e.g. `NHS`, `Ministry of Defence`, `Leeds City Council`. |
| `stages` | `planning`, `tender`, `award`, `contract`. Leave empty for all. |
| `noticeTypes` | Procurement Act notice types, e.g. `UK4` (tender), `UK6` (contract award). |
| `minValue`, `maxValue` | Estimated value, or the award value for awards, in pounds. Notices with no published value are kept. |
| `publishedWithinDays` | Notices published in the last N days (default 7, up to 366). |
| `publishedSince` | Or a start date (YYYY-MM-DD). |
| `deadlineAfter` | Bid deadline on or after a date: `YYYY-MM-DD`, `today` (still open) or `7 days` (at least a week left). |
| `smeSuitableOnly` | Only notices the buyer marked suitable for SMEs. |
| `includeUpdates` | Include changed notices (new deadline, corrections). On by default; each has `isUpdate: true`. |
| `sources` | `find-a-tender` and/or `contracts-finder` (both by default). |
| `onlyNewNotices` | Skip notices this search returned on earlier runs. Pair it with a schedule. |
| `includeDescription` | Plain-text description, up to 4,000 characters (on by default). |
| `maxResults` | Cap (default 1,000). |

**Open IT tenders in London and the South East worth £100k or more:**

```json
{
    "cpvCodes": ["72", "48"],
    "regions": ["London", "South East"],
    "stages": ["tender"],
    "deadlineAfter": "today",
    "minValue": 100000
}
```

**Daily tender alert (run on a schedule, e.g. every morning at 7am):**

```json
{
    "keywords": ["cleaning", "facilities management", "grounds maintenance"],
    "regions": ["North West", "Yorkshire and the Humber"],
    "stages": ["planning", "tender"],
    "publishedWithinDays": 2,
    "onlyNewNotices": true
}
```

Set up the schedule in Apify Console (Schedules → Create), then send the results where you want them with an
integration: email, Slack, Google Sheets, or a webhook into your CRM. A two-day window with `onlyNewNotices` means a
missed run never loses anything.

**Who won NHS software contracts this year:**

```json
{
    "buyerNames": ["NHS"],
    "cpvCodes": ["48"],
    "stages": ["award"],
    "publishedSince": "2026-01-01",
    "includeDescription": false
}
```

### Output

One row per notice, the same shape from both services:

```json
{
    "source": "find-a-tender",
    "noticeId": "100188-2026",
    "ocid": "ocds-h6vhtk-078e4f",
    "noticeType": "UK4",
    "noticeTypeName": "Tender notice",
    "stage": "tender",
    "isUpdate": false,
    "title": "Yorkshire Highway Alliance Road Markings Framework 2026-28",
    "description": "Implementation of road markings within Leeds and across the Yorkshire Highway Alliance",
    "buyerName": "Leeds City Council",
    "buyerId": "GB-PPON-PJYG-6658-PPMY",
    "buyerRegion": "UKE42",
    "buyerRegionName": "Yorkshire and the Humber",
    "buyerTown": "Leeds",
    "buyerPostcode": "LS1 1UR",
    "buyerEmail": "contracts.support.unit@leeds.gov.uk",
    "deliveryRegions": [],
    "cpvCodes": ["34922100", "45233210"],
    "cpvDescriptions": ["Road markings", "Surface work for highways"],
    "category": "works",
    "valueMin": null,
    "valueMax": 7200000,
    "currency": "GBP",
    "publishedAt": "2026-10-22T16:08:58.000Z",
    "tenderDeadline": "2026-11-19T12:00:00.000Z",
    "contractStart": "2026-12-14T00:00:00.000Z",
    "contractEnd": "2028-12-13T23:59:59.000Z",
    "procedureType": "Open procedure",
    "lotCount": 1,
    "suitableForSme": null,
    "suitableForVcse": null,
    "awardedSuppliers": [],
    "awardValue": null,
    "awardDate": null,
    "noticeUrl": "https://www.find-tender.service.gov.uk/Notice/100188-2026",
    "documentsUrl": "https://leedscitycouncil.ukp.app.jaggaer.com/esop/ogc-host/public/leedscitycouncil/web/login.html"
}
```

For awards, `awardedSuppliers`, `awardValue` and `awardDate` are filled in. Fields a notice doesn't publish are
`null`. Values are net of VAT where the notice gives both figures. `stage` is one of:

- `planning`: pipeline (UK1), preliminary market engagement (UK2) and planned procurement (UK3) notices
- `tender`: tender notices (UK4), procurement terminations (UK12) and dynamic markets (UK14 to UK16)
- `award`: contract award (UK6) and transparency (UK5, direct award) notices
- `contract`: contract details (UK7), performance (UK9), change (UK10) and termination (UK11) notices

### Pricing

**$0.003 per notice returned**, plus a token $0.00005 per run. 1,000 notices cost about $3. A daily alert that finds
20 new notices costs about $1.80 a month. Notices your filters drop cost nothing.

### Good to know

- Since the **Procurement Act 2023** went live on 24 February 2025, Find a Tender carries every notice under the new
  rules, above and below threshold, with a UK notice type (UK1 to UK16). Contracts Finder still carries notices for
  procurements started under the old rules, mostly awards now, so both are searched by default. Scottish buyers
  publish on Public Contracts Scotland, and only their above-threshold notices reach Find a Tender.
- Every change to a notice is published as a new notice. The actor returns only the latest version of each
  procurement stage, and copies of the same notice on both services are returned once.
- Both services limit how fast they can be read, so the actor reads one page of 100 notices every 5 seconds: a week
  of everything takes about 3 minutes, a day well under a minute. Filters are applied as it reads.
- Contracts Finder notices have no region code, so the buyer's region is looked up from its postcode
  (postcodes.io).
- `onlyNewNotices` remembers results in a named key-value store in your Apify account (`uk-public-tenders-seen`),
  separately for each set of filters. Change the filters and it starts afresh; delete the store to reset them all.
- Keywords match the title and description only, not attached documents.

### Use it from Claude, ChatGPT or Cursor (MCP)

AI assistants can call this actor as a tool through Apify's MCP server. Add this server URL to your MCP client and
sign in with your Apify account when prompted:

```
https://mcp.apify.com?tools=onibaku/uk-public-tenders
```

### Data source

[Find a Tender](https://www.find-tender.service.gov.uk/) OCDS release package API and
[Contracts Finder](https://www.contractsfinder.service.gov.uk/) OCDS search API, both run by the Cabinet Office.
Notice data is published under the
[Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/).
Contains public sector information licensed under the Open Government Licence v3.0. Buyer regions for Contracts
Finder notices come from [postcodes.io](https://postcodes.io/) (ONS data, OGL). Every row's `noticeUrl` links to the
official notice.

This actor isn't affiliated with or endorsed by the Cabinet Office.

Questions or feature requests? Open an issue on the actor's Issues tab or email admin@onibaku.co.uk.

# Actor input Schema

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

Matched against the notice title and description, case-insensitive, at the start of a word: "software", "facilities management", "cyber". Leave empty for every notice.

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

Drop notices whose title or description contains any of these, e.g. "framework".

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

Prefix match on the notice's CPV codes: "72" is all IT services, "4521" building construction work, "79620000" supply of staff. Trailing zeros are ignored, so 72000000 means the same as 72.

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

Region names (London, North West, Scotland, Wales, England...) or NUTS/ITL codes (UKI, UKD3, TLM). Matched against the buyer's address and the delivery locations.

## `includeUkWide` (type: `boolean`):

Keep notices delivered across the whole UK when you filter by region.

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

Part of the contracting authority's name, e.g. "NHS", "Leeds City Council", "Ministry of Defence".

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

Leave empty for all. Planning = pipeline, market engagement and planned procurement notices; Tender = open opportunities; Award = contract awards and transparency (direct award) notices; Contract = contract details, changes and terminations.

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

Find a Tender notice types since the Procurement Act 2023, e.g. UK4 (tender notice), UK6 (contract award), UK1 (pipeline), UK2 (preliminary market engagement), UK3 (planned procurement), UK5 (transparency). Leave empty for all. Setting this leaves out Contracts Finder and older-regime notices, which have no UK type.

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

Estimated or awarded value. Notices with no published value are kept.

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

Estimated or awarded value. Notices with no published value are kept.

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

Ignored when "Published on or after" is set. Up to 366.

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

A date (YYYY-MM-DD). Overrides "Published in the last N days".

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

Only notices with a bid deadline on or after this date: YYYY-MM-DD, "today" or "7 days" (from now). "today" keeps only opportunities still open, and stays right on a schedule. Notices without a deadline are left out when this is set.

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

The buyer says the contract (or a lot) is suitable for small and medium-sized businesses.

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

Changes to earlier notices (new deadline, corrected details). They come through as their own notice with isUpdate = true.

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

Find a Tender carries everything under the Procurement Act 2023, at any value. Contracts Finder still carries notices for procurements started under the old rules.

## `onlyNewNotices` (type: `boolean`):

Remembers the notices each run of this search returned and skips them next time. Use with a schedule for tender alerts.

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

Plain text, up to 4,000 characters. Turn off for smaller output.

## `maxResults` (type: `integer`):

Stop after this many notices.

## Actor input object example

```json
{
  "keywords": [
    "software"
  ],
  "includeUkWide": true,
  "publishedWithinDays": 3,
  "smeSuitableOnly": false,
  "includeUpdates": true,
  "sources": [
    "find-a-tender",
    "contracts-finder"
  ],
  "onlyNewNotices": false,
  "includeDescription": true,
  "maxResults": 1000
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `results` (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 = {
    "keywords": [
        "software"
    ],
    "publishedWithinDays": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("onibaku/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"],
    "publishedWithinDays": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("onibaku/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"
  ],
  "publishedWithinDays": 3
}' |
apify call onibaku/uk-public-tenders --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,onibaku/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/5JDVqzgb0QOueTrSM/builds/CtPZq1q7HJxbREnTz/openapi.json
