# Find a Tender API: UK Tenders Feed (Unofficial) (`graylabs/uk-find-a-tender`) Actor

Pull UK public procurement notices from Find a Tender (FTS) as structured data: tenders, contract awards, buyers, CPV codes, values and deadlines. Official OCDS feed, no API key. Filter by date, CPV, region and value, and track new or changed notices. Not affiliated with the Cabinet Office.

- **URL**: https://apify.com/graylabs/uk-find-a-tender.md
- **Developed by:** [Gray Labs](https://apify.com/graylabs) (community)
- **Categories:** Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.00 / 1,000 tender 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

## Find a Tender API: UK Tenders Feed (Unofficial)

### What does Find a Tender API: UK Tenders Feed do?

It pulls UK public procurement notices from **Find a Tender (FTS)**, the UK government's service for higher-value public contracts, and returns them as clean, flat rows you can download as JSON, CSV or Excel or read through the Apify API. It reads the official, keyless OCDS feed, so you need no account or API key.

Each row is one notice: **tenders** (open opportunities), **contract awards** and contract details, and **planning** notices (market engagement and pipeline). Rows include the **buyer**, **CPV codes**, **estimated and awarded values**, **deadlines**, regions, contract dates and a link to the original notice.

Use it for **UK tenders** monitoring, bid pipelines, market sizing and procurement research.

### What data can you extract?

| Field                                                                             | Meaning                                                                                                                                |
| --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `noticeId`, `procurementId`                                                       | Find a Tender notice ID (e.g. 100218-2026) and the OCDS procurement ID that links notices of one procurement                           |
| `noticeUrl`                                                                       | Link to the original notice on Find a Tender                                                                                           |
| `title`, `noticeKind`, `noticeType`, `releaseTags`                                | Title; planning / tender / award / other; notice form (e.g. UK4 tender notice, UK6 contract award notice, UK7 contract details notice) |
| `tenderStatus`, `procedureType`, `legalBasis`, `contractNature`, `aboveThreshold` | Status, procedure, legal basis, goods / services / works, above-threshold flag                                                         |
| `buyerName`, `buyerRegion`                                                        | Buying organisation and its region code (ITL/NUTS, e.g. UKI34)                                                                         |
| `deliveryRegions`                                                                 | Region codes where the contract is delivered                                                                                           |
| `cpvCodes`, `mainCpvCode`, `mainCpvDescription`                                   | CPV classification                                                                                                                     |
| `estimatedValue`, `estimatedValueInclVat`, `estimatedValueCurrency`               | Estimated value (excluding VAT, and including VAT when given). Sum of lots when there is no overall value                              |
| `awardedValue`, `awardedValueCurrency`                                            | Total awarded value (award notices)                                                                                                    |
| `lotCount`, `deadlineAt`, `contractStart`, `contractEnd`                          | Lots, tender deadline (not set on awards), contract period                                                                             |
| `suitableForSme`, `suitableForVcse`                                               | Whether any lot is marked suitable for SMEs / VCSEs                                                                                    |
| `suppliers`, `suppliersWithheld`                                                  | Winning organisations (only with `includeSuppliers`, see Privacy)                                                                      |
| `description`                                                                     | Free-text description (only with `includeDescriptions`)                                                                                |
| `changeStatus`                                                                    | new / updated / unchanged (only with change tracking)                                                                                  |
| `publishedAt`, `retrievedAt`, `attribution`, `notice`                             | Dates, the Open Government Licence attribution and a non-affiliation line on every row                                                 |

### How to use it

1. Click **Try for free** and keep the prefilled input (last 3 days, 20 notices), or set your filters.
2. Run it. Rows appear in the **Output** tab; download them in any format.
3. To get only new or changed notices every day, turn on **Track changes** and **Only new or updated**, and schedule the Actor.

Filters: date window (last N days or from/to dates, up to 90 days), notice kind, CPV codes (broader codes include sub-codes), regions (ITL/NUTS prefix, e.g. UKI = London), keywords (title and description), and minimum/maximum value.

### Input examples

Daily new IT tenders (CPV 72000000 and 48000000), only new or changed ones:

```json
{
    "lastNDays": 1,
    "noticeKinds": ["tender"],
    "cpvCodes": ["72000000", "48000000"],
    "maxResults": 500,
    "trackChanges": true,
    "onlyNewOrUpdated": true
}
```

Contract awards over 100,000 in London in the last week, with winning organisations:

```json
{
    "lastNDays": 7,
    "noticeKinds": ["award"],
    "regions": ["UKI"],
    "minValue": 100000,
    "includeSuppliers": true,
    "maxResults": 1000
}
```

Construction pipeline (planning notices) matching keywords:

```json
{
    "lastNDays": 3,
    "noticeKinds": ["planning"],
    "keywords": ["construction", "refurbishment"],
    "maxResults": 200
}
```

### Output example

```json
{
    "noticeId": "100649-2026",
    "procurementId": "ocds-h6vhtk-078f61",
    "noticeUrl": "https://www.find-tender.service.gov.uk/Notice/100649-2026",
    "sourceName": "UK Find a Tender service (Cabinet Office)",
    "title": "External Audit Services",
    "noticeKind": "award",
    "releaseTags": ["award", "contract"],
    "noticeType": null,
    "tenderStatus": "complete",
    "procedureType": "Award procedure without prior publication of a call for competition",
    "legalBasis": "CELEX 32014L0024",
    "contractNature": "services",
    "aboveThreshold": null,
    "buyerName": "Citizen Housing Group Ltd",
    "buyerRegion": "UKG32",
    "deliveryRegions": ["UKG"],
    "cpvCodes": ["79212000"],
    "mainCpvCode": "79212000",
    "mainCpvDescription": "Auditing services",
    "estimatedValue": null,
    "estimatedValueInclVat": null,
    "estimatedValueCurrency": null,
    "awardedValue": 600000,
    "awardedValueCurrency": "GBP",
    "lotCount": 1,
    "publishedAt": "2026-10-23T15:27:46+01:00",
    "deadlineAt": null,
    "contractStart": null,
    "contractEnd": null,
    "suitableForSme": null,
    "suitableForVcse": null,
    "suppliers": ["Menzies LLP"],
    "suppliersWithheld": 0,
    "description": "This contract will include 2 work streams. This will cover all of Citizen's external audit requirements, and a separate audit on Citizen's decarbonisation program. This contract will commence 1st November 2026, and will be let for 48 months.",
    "changeStatus": null,
    "attribution": "Contains public sector information licensed under the Open Government Licence v3.0. Licence: https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/. Source: Find a Tender, https://www.find-tender.service.gov.uk. Normalised by this Actor; not an official reproduction.",
    "notice": "Unofficial. Not affiliated with or endorsed by Find a Tender, the Cabinet Office or Crown Commercial Service.",
    "retrievedAt": "2026-10-23T14:28:12.732Z"
}
```

### How much does it cost?

- **$0.01 per run start** plus **$6 per 1,000 notices saved** ($0.006 each, the `tender` event). Example: 1,000 notices = $0.01 + $6 = $6.01.
- You pay only for rows that are saved. Rows skipped as duplicates, invalid, filtered out or unchanged are free.
- Set **Maximum cost per run** when you start a run; the Actor stops when it reaches your cap.

### Privacy: organisations only

Notices list contact people, emails, phone numbers and street addresses. This Actor **never outputs them**. Rows carry organisation-level data only. Descriptions are off by default; when on, email addresses and phone numbers are replaced with placeholders, but names written inside free text can remain.

Supplier names are off by default. With `includeSuppliers`, a winner is shown only if it is registered with Companies House, a charity register or another organisation register, or its name looks like an organisation (Ltd, LLP, Council, Trust and similar). Anything else is withheld and counted in `suppliersWithheld`, because winners can be sole traders. This is a heuristic: it can withhold some real companies.

### Limits

- The date window uses the date a notice was **published or last updated** (that is how the official feed filters).
- **Deadlines exist only on tender and planning notices.** Award and contract notices have no `deadlineAt`, so in a mixed feed about 80% of rows have no deadline. To get only open opportunities with deadlines, set **Notice kinds** to `tender`.
- **Regions are ITL/NUTS codes, not place names.** Use a code prefix such as `UKI` (London), `UKM` (Scotland) or `UKD3` (Greater Manchester). A place name like "London" will not match.
- Find a Tender covers higher-value UK procurement. Lower-value UK contracts are published on Contracts Finder, which this Actor does not read.
- Values are in the notice's own currency; there is no conversion. Notices without a value are excluded when a value filter is set.
- Output is a normalised copy, not an official reproduction. Check the original notice before bidding.
- `maxRequests` (default 60, up to 100 notices per request) caps API calls per run.

### FAQ

**Do I need an API key?** No. The feed is public and keyless.

**Is the data free to reuse?** Find a Tender states: "All content is available under the Open Government Licence v3.0, except where otherwise stated". Every row carries the OGL attribution and licence link. This is not legal advice.

**How fresh is it?** Each run reads the live feed. Schedule it daily for alerts.

Unofficial. Not affiliated with or endorsed by Find a Tender, the Cabinet Office or Crown Commercial Service.

# Changelog

This Actor's version history is a separate document: https://apify.com/graylabs/uk-find-a-tender/changelog.md

# Actor input Schema

## `lastNDays` (type: `integer`):

Notices published or last updated in the last N days (UTC), including today. Default 3. Ignored if you set a from or to date. Maximum 90.

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

Start of the window (UTC, inclusive). Find a Tender filters on the date a notice was published or last updated.

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

End of the window (UTC, inclusive). Defaults to today.

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

Match any of these words or phrases in the notice title or description (case-insensitive).

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

8-digit CPV codes, e.g. 72000000 (IT services). Broader codes include their sub-codes (72000000 matches 72220000).

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

E.g. UKI (London), UKF2, UKM (Scotland). Matches delivery regions or the buyer's region by prefix, so UKI includes UKI34.

## `noticeKinds` (type: `array`):

Planning (market engagement, pipeline), tender (open opportunities), award (contract awards and contract details) or other. Empty = all.

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

In the notice's own currency (no conversion). Uses the estimated value (excl. VAT, else incl. VAT), else the awarded value. Notices with no value are excluded when a value filter is set.

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

In the notice's own currency (no conversion).

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

Stop after saving this many notices (each saved notice is one charged result).

## `maxRequests` (type: `integer`):

Safety cap on Find a Tender API calls per run (up to 100 notices each). Default 60.

## `includeSuppliers` (type: `boolean`):

Off by default. When on, award notices list winning organisations only. Names that may belong to individuals are withheld and counted.

## `includeDescriptions` (type: `boolean`):

Off by default. Adds the notice's free-text description (up to 10,000 characters), in the original language.

## `trackChanges` (type: `boolean`):

Mark each notice new, updated or unchanged compared with earlier runs of the same search.

## `onlyNewOrUpdated` (type: `boolean`):

With change tracking, skip notices already seen unchanged (they are not charged).

## Actor input object example

```json
{
  "lastNDays": 3,
  "keywords": [],
  "cpvCodes": [],
  "regions": [],
  "noticeKinds": [],
  "maxResults": 20,
  "maxRequests": 60,
  "includeSuppliers": false,
  "includeDescriptions": false,
  "trackChanges": false,
  "onlyNewOrUpdated": false
}
```

# Actor output Schema

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

No description

## `runSummary` (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 = {
    "lastNDays": 3,
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("graylabs/uk-find-a-tender").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 = {
    "lastNDays": 3,
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("graylabs/uk-find-a-tender").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 '{
  "lastNDays": 3,
  "maxResults": 20
}' |
apify call graylabs/uk-find-a-tender --silent --output-dataset

```

## MCP server setup

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

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/mtYf5NeD8Gl304aMe/builds/l8NeuZ3NbxljMVdVW/openapi.json
