# Government Tenders & Public Procurement Tracker (`cleanpull/public-tenders-tracker`) Actor

Government tenders, procurement opportunities and contract awards from UK Find a Tender, Contracts Finder, EU TED, AusTender and SAM.gov in one schema: keywords, CPV, NAICS and UNSPSC codes, deadlines, values in one currency and new-only alerts. Official feeds only.

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

## Pricing

from $1.60 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Government Tenders & Public Procurement Tracker

Find government tenders and contract awards from **five official sources in one schema**: **UK Find a Tender**, **UK Contracts Finder**, **EU TED** (every EU and EEA country), **AusTender** (Australia) and **US SAM.gov**. Search by keyword, by **topic across CPV, NAICS, PSC and UNSPSC codes**, by country, buyer, deadline and value (converted to **one currency** at the ECB rate), and get **only what changed since your last run**: new notices, updated deadlines or values, cancellations, and **awards of the tenders you were watching**. A **daily digest** lists what is closing soon, the largest notices and recent winners. Official feeds only, no scraping of logins, from **$2 per 1,000 notices**.

### What you can do with it

- **Find bids to win**: "IT services tenders in the UK, EU, US and Australia, open for at least 10 more days, worth over $100,000."
- **Watch your market daily**: schedule a run with Changes only and get new tenders, changed deadlines and values, and cancellations, without the ones you already saw.
- **See who wins**: add the Awarded stage and get winners, award values and dates; with monitoring, the tenders you were watching come back as `awarded` with the winner.
- **Build a pipeline**: the Planned stage adds prior information notices, UK pipeline notices and US sources-sought and presolicitations, months before the tender.
- **Feed a CRM, sheet or Slack**: flat rows for spreadsheets, one digest record per run for a message.

### Why this actor

- **Five official sources, one record.** The same fields for every notice: title, buyer, country, stage, deadline (with its time zone), value, codes, documents and submission links, award and winners. Nothing to stitch together.
- **Topics that cross code lists.** "Construction", "Cyber security", "Cleaning" and 33 more topics map to CPV (UK, EU), NAICS and PSC (US) and UNSPSC (Australia), so one search finds the same kind of work everywhere. Each notice lists its topics. Codes can be given directly too, as prefixes (`72`, `5415`, `8111`).
- **Reliable by design.** Official APIs and data files: UK OCDS APIs, the TED search API, AusTender's OCDS API and its official open-tender feed, and SAM.gov's public daily extract. Both UK services share a rate limit; the actor paces them and waits when asked, so runs finish instead of failing.
- **Monitoring that follows a procurement.** Notices are tracked by procurement (OCDS ocid, TED procedure id, SAM solicitation number), so an award or a cancellation of a watched tender is reported as a change to it, with what changed.
- **Values you can compare.** Every value is also given in your currency at the European Central Bank's rate of the day; value filters work across sources.
- **Compliant with each source's terms.** SAM.gov comes from its public extract, not its website search; AusTender's tender text (which belongs to the issuing agency) is given as an excerpt with the link; each record carries its source's licence.

### Input

| Field                                                     | Type                     | What it does                                                                  |
| --------------------------------------------------------- | ------------------------ | ----------------------------------------------------------------------------- |
| `sources`                                                 | array                    | `uk-fts`, `uk-cf`, `eu-ted`, `au-austender`, `us-sam` (default all)           |
| `keywords`, `excludeKeywords`                             | arrays                   | Words in the title or description (TED searches its full text)                |
| `topics`                                                  | array                    | Topics across code lists (see the input form for all 36)                      |
| `cpvCodes`, `naicsCodes`, `pscCodes`, `unspscCodes`       | arrays                   | Codes or prefixes                                                             |
| `countries`                                               | array                    | Buyer countries as two-letter codes                                           |
| `buyerKeywords`                                           | array                    | Words in the buyer's name                                                     |
| `stages`                                                  | array                    | `planning`, `tender` (default), `award`, `contract`, `cancelled`              |
| `publishedWithinDays`, `publishedFrom`                    | integer, date            | The publication window (default 7 days)                                       |
| `openOnly`, `deadlineWithinDays`, `minDaysToDeadline`     | boolean, integers        | Open tenders only; closing within N days; at least N days to bid              |
| `minValue`, `maxValue`, `valueCurrency`, `includeNoValue` | numbers, string, boolean | Value range in one currency; keep notices without a value or not              |
| `smeOnly`, `setAsides`                                    | boolean, array           | Small-business suitable only (UK SME flag, US set-asides); US set-aside types |
| `monitorMode`, `monitorName`, `changeTypes`               | boolean, string, array   | Changes only: `new`, `updated`, `cancelled`, `awarded`                        |
| `outputFormat`                                            | `notices`, `flat`        | Full records or flat rows                                                     |
| `includeDigest`                                           | boolean                  | One summary record per run (default on)                                       |
| `descriptionMaxLength`, `includeRaw`                      | integer, boolean         | Description length; the source's original record too                          |
| `maxItems`, `maxNoticesPerSource`                         | integers                 | Limits                                                                        |
| `fields`                                                  | array                    | Return only these fields                                                      |

#### Example inputs

Open IT tenders worth $100,000 or more, at least 10 days to bid:

```json
{
  "topics": ["IT services", "Software"],
  "minValue": 100000,
  "valueCurrency": "USD",
  "minDaysToDeadline": 10
}
```

A daily watch of construction tenders in Ireland and the UK, with awards:

```json
{
  "sources": ["uk-fts", "uk-cf", "eu-ted"],
  "topics": ["Construction"],
  "countries": ["IE", "GB"],
  "monitorMode": true,
  "monitorName": "construction-ie-uk",
  "publishedWithinDays": 2
}
```

Who won IT contracts in Australia and the US this month:

```json
{
  "sources": ["au-austender", "us-sam"],
  "topics": ["IT services"],
  "stages": ["award", "contract"],
  "publishedWithinDays": 30
}
```

### Output

Every notice has `source`, `sourceName`, `id`, `ocid`, `url`, `title`, `description`, `stage`, `noticeType`, `procedure`, `contractNature`, `buyer` (`name`, `id`, `country`), `buyerEmail`, `country`, `placeOfPerformance`, `publishedAt`, `deadline`, `daysToDeadline`, `value` and `valueConverted`, `codes` (`cpv`, `naics`, `psc`, `unspsc`), `topics`, `sme`, `setAside`, `documentsUrl`, `submissionUrl`, `award` (`date`, `value`, `suppliers`) and `awardValueConverted`, `licence` and `scrapedAt`. In monitoring, `change` says `new`, `updated` (with each changed field, from and to), `cancelled` or `awarded`, and the stage before.

The digest record (`recordType: "digest"`) has counts by source, stage and change, the tenders closing within 7 days, the 10 largest notices, recent awards with winners, top buyers and top topics.

Every run writes `RUN_SUMMARY` to the key-value store: the outcome (`COMPLETE`, `PARTIAL`, `NO_CHANGES`, `EMPTY` or `FAILED`), notices read and requests per source, any source that could not be read, the ECB rate date, charges and warnings.

### Pricing

Pay only for results.

| Event                                                              | Free and Bronze | Silver | Gold  |
| ------------------------------------------------------------------ | --------------- | ------ | ----- |
| Notice                                                             | $2.00           | $1.80  | $1.60 |
| Change (changes only: a new, updated, cancelled or awarded notice) | $2.00           | $1.80  | $1.60 |
| Unchanged notice checked (changes only)                            | $0.10           | $0.09  | $0.08 |
| Digest (one per run)                                               | $5.00           | $4.50  | $4.00 |

Prices are per 1,000 (the digest is $0.005 a run). Each run also has a $0.00005 start fee.

### Sources and licences

| Source              | Feed                                                                            | Licence                                                                                                       |
| ------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| UK Find a Tender    | OCDS API                                                                        | Open Government Licence v3.0                                                                                  |
| UK Contracts Finder | OCDS API                                                                        | Open Government Licence v3.0                                                                                  |
| EU TED              | Search API v3                                                                   | Reuse of Commission documents (Decision 2011/833/EU)                                                          |
| AusTender           | OCDS API (contract notices); current ATM list feed and ATM pages (open tenders) | CC BY 3.0 AU, Commonwealth of Australia; ATM material remains with the issuing agency (excerpt and link only) |
| US SAM.gov          | Contract Opportunities public daily extract                                     | US government work                                                                                            |

Contains public sector information licensed under the Open Government Licence v3.0. AusTender data © Commonwealth of Australia, CC BY 3.0 AU.

### Limits

- Notices as the sources publish them: not every notice has a value, a deadline time or codes; such fields are null. Value filters keep notices without a value unless `includeNoValue` is off.
- Topics are an approximate bridge: the code lists do not map one to one.
- UK runs are paced (both UK services share a rate limit of 12 requests a minute), so a long UK window takes a while: about 6 minutes for a week, 25 for a month. A run never times out with nothing: a few minutes before its time limit it stops reading, delivers what it has, says which source stopped early, and ends PARTIAL. Raise the run timeout (or narrow the period or keywords) to read everything in one run. TED's notice titles and descriptions are in the buyer's language when no English version exists.
- SAM.gov's extract is refreshed once a day (early morning US time), so the newest SAM notices can be up to a day old. AusTender's open-tender feed lists the latest approaches to market; very old open tenders are not included.
- AusTender ATM descriptions are an excerpt (the agencies' text); the full text and documents are on the linked page.
- AusTender publishes its open tenders (ATMs) and its contract notices without a link between them, so for Australia monitoring reports new and changed notices, but cannot mark a watched ATM as awarded.
- The dataset views (Notices, Awards, Changes, Digest) are for the full notice format; flat rows are for spreadsheet export.
- **Nothing found**: no notice matching the search is a successful, empty run, never charged; input that cannot be searched (an unknown topic, a bad country code) ends the run with one free `recordType: "unreadable"` row saying why, also successful. Only a run where every source failed fails.

### Changelog

- **0.1.x, reliability** (2026-10-24): input that cannot be searched ends SUCCEEDED with a free `unreadable` row saying why, instead of FAILED; empty sources, stages and change lists, country codes and the start date are checked in the input form; fetching stops at the shared run deadline (or 4 minutes before the limit, whichever is earlier). Prices and events unchanged.
- **0.1.4** (October 2026): a run near its time limit delivers what it has read instead of timing out; progress per source in the status.
- **0.1** (October 2026): UK Find a Tender, UK Contracts Finder, EU TED, AusTender and SAM.gov in one schema; keywords, topics across code lists, countries, buyers, deadlines, values in one currency, SME and set-aside filters; awards; changes-only monitoring by procurement; digest; flat rows.

# Actor input Schema

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

Official sources to search: UK Find a Tender and Contracts Finder, EU TED, AusTender and SAM.gov. All public, official feeds.

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

Optional. Keep notices whose title or description contains any of these words or phrases ("cyber security", "cleaning"). TED searches its full text on its side.

## `topics` (type: `array`):

Optional. Topics matched through each source's own codes (CPV in the UK and EU, NAICS and PSC in the US, UNSPSC in Australia), so one topic finds the same kind of work everywhere: IT services, Software, Cyber security, Cloud and hosting, Data and analytics, Telecommunications, Computer hardware, Construction, Architecture and engineering, Facilities management, Cleaning, Security services, Catering and food, Consulting, Legal services, Accounting and audit, Financial and insurance, Marketing and advertising, Printing and publishing, Translation, Recruitment and HR, Training and education, Healthcare services, Medical equipment, Research and development, Transport and logistics, Vehicles, Energy and utilities, Environmental and waste, Furniture, Office supplies, Defence and security equipment, Real estate, Agriculture and forestry, Repair and maintenance, Water and sewerage.

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

Optional. CPV codes or prefixes (72000000, 7221): UK and EU notices.

## `naicsCodes` (type: `array`):

Optional. NAICS codes or prefixes (541512, 5415): US notices.

## `unspscCodes` (type: `array`):

Optional. UNSPSC codes or prefixes (81112000, 8111): Australian notices.

## `pscCodes` (type: `array`):

Optional. US Product and Service Codes or prefixes (D3, R4).

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

Optional. Buyer countries as two-letter codes (DE, FR, IE, GB, US, AU…). For TED this narrows the search to those EU and EEA countries.

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

Optional. Keep notices whose buyer name contains any of these ("NHS", "Department of Defense", "Bundeswehr").

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

Optional. Leave out notices whose title or description contains any of these.

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

Which notices to return. Open for bids is what bid teams want; add Awarded for award intelligence (who won, at what value).

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

Notices published in this many days, today included.

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

Optional. A start date (YYYY-MM-DD) instead of the number of days.

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

Leave out tenders whose deadline has passed.

## `deadlineWithinDays` (type: `integer`):

Optional. Only tenders closing within this many days.

## `minDaysToDeadline` (type: `integer`):

Optional. Leave out tenders closing sooner than this, too soon to bid.

## `minValue` (type: `number`):

Optional. In the currency below, converted at the ECB rate of the day.

## `maxValue` (type: `number`):

Optional. In the currency below.

## `valueCurrency` (type: `string`):

Values are converted to this currency (valueConverted) at the European Central Bank's daily rate; value filters use it.

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

Many notices publish no value. With a value filter, keep them (on) or leave them out (off).

## `smeOnly` (type: `boolean`):

Only notices marked suitable for small businesses (UK SME flag, US small-business set-asides).

## `setAsides` (type: `array`):

Optional. US set-aside types to keep ("Small Business", "8(a)", "SDVOSB", "HUBZone", "Women-Owned").

## `monitorMode` (type: `boolean`):

Return only what changed since the last run under the same name: new notices, updated deadlines or values, cancellations, and awards of tenders you were watching. Schedule it daily.

## `monitorName` (type: `string`):

Runs with the same name share one memory.

## `changeTypes` (type: `array`):

Which changes count.

## `outputFormat` (type: `string`):

How results are shaped.

## `includeDigest` (type: `boolean`):

One summary record per run: counts by source and stage, tenders closing within 7 days, the largest notices, recent awards, top buyers and topics. For an email or Slack message.

## `descriptionMaxLength` (type: `integer`):

Characters of description to keep (0 for none). AusTender descriptions are always an excerpt.

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

Also return each source's original record (OCDS, TED fields, SAM.gov row) for anything not in the schema.

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

Optional. Stop after this many notices in the run.

## `maxNoticesPerSource` (type: `integer`):

A safety limit on how many notices are read from each source before filtering.

## `fields` (type: `array`):

Optional. Keep only these fields, for example \["title", "buyer.name", "deadline", "url"].

## Actor input object example

```json
{
  "sources": [
    "uk-fts",
    "uk-cf",
    "eu-ted",
    "au-austender"
  ],
  "keywords": [
    "software"
  ],
  "stages": [
    "tender"
  ],
  "publishedWithinDays": 7,
  "openOnly": true,
  "valueCurrency": "USD",
  "includeNoValue": true,
  "smeOnly": false,
  "monitorMode": false,
  "monitorName": "default",
  "changeTypes": [
    "new",
    "updated",
    "cancelled",
    "awarded"
  ],
  "outputFormat": "notices",
  "includeDigest": true,
  "descriptionMaxLength": 2000,
  "includeRaw": false,
  "maxNoticesPerSource": 5000
}
```

# Actor output Schema

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

No description

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

No description

## `awards` (type: `string`):

No description

## `changes` (type: `string`):

No description

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

Outcome, per-source counts and errors, charges and warnings.

# 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 = {
    "sources": [
        "uk-fts",
        "uk-cf",
        "eu-ted",
        "au-austender"
    ],
    "keywords": [
        "software"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cleanpull/public-tenders-tracker").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 = {
    "sources": [
        "uk-fts",
        "uk-cf",
        "eu-ted",
        "au-austender",
    ],
    "keywords": ["software"],
}

# Run the Actor and wait for it to finish
run = client.actor("cleanpull/public-tenders-tracker").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 '{
  "sources": [
    "uk-fts",
    "uk-cf",
    "eu-ted",
    "au-austender"
  ],
  "keywords": [
    "software"
  ]
}' |
apify call cleanpull/public-tenders-tracker --silent --output-dataset

```

## MCP server setup

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

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/iFr3dKgZIlM6A2O3h/builds/vsB5Z7D4LF0w61top/openapi.json
