# UK Contract Award Winner Supplier Leads (`afkdigital/newapi19-contract-award-winner-leads`) Actor

Find official UK public contract winners from Find a Tender and Contracts Finder: verified award amounts, suppliers, buyer, dates, contracts and lot identifiers. Not evidence of available subcontracting. No automatic messages. EU TED not currently supported on Apify.

- **URL**: https://apify.com/afkdigital/newapi19-contract-award-winner-leads.md
- **Developed by:** [AFK Digital](https://apify.com/afkdigital) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$7.00 / 1,000 unique awarded contract or lots

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 Contract Award Winner Supplier Leads

**NEWAPI19** | Actor **newapi19-contract-award-winner-leads** | Version 1.0.0

Find recently published **official UK public-sector contract award results** and identify suppliers that won contracts. These are leads for independent business research, **not verified subcontracting opportunities**. The Actor never sends outreach or marketing messages.

### Real supported sources

| Source | Geographic coverage | Official interface | Monetary amount and date |
|---|---|---|---|
| UK Find a Tender | GB | OCDS 1.1 release-package API, award stage, pagination cursor | Linked contract value or award value; award date if supplied; contract-signing date in separate field |
| UK Contracts Finder | GB | Official OCDS award-stage release search, pagination cursor | Award value and award decision date |
| TED eForms (NOT LIVE ON APIFY) | EU-27 | TED Search API v3 and original XML, validated on Netcup but Apify cloud returned HTTP 202 empty XML | Source adapter retained for future re-enablement after platform validation |

**Supported paid Store scope is GB ONLY.** EU TED eForms mapping was independently verified on Netcup using real Spain and Croatia award notices. However, the official TED XML endpoint returned HTTP 202 with no body from Apify hosting on 2026-10-22. To avoid false results and paid failures, TED is disabled on the hosted Actor until that source becomes reliably accessible. EU is NOT a supported Store country at release.

### Example input (small QA-safe default)

```json
{
  "sources": ["find_a_tender", "contracts_finder"],
  "countries": ["GB"],
  "cpvCodes": [],
  "daysBack": 7,
  "minAwardValue": "0",
  "currency": "",
  "maxResults": 10,
  "maxChargeUsd": "0.07",
  "requireAwardValue": true,
  "maxPagesPerSource": 2,
  "maxRequests": 50,
  "maxRunSeconds": 240
}
```

LOCAL TED ADAPTER EXPERIMENT ONLY, NOT USABLE ON APIFY UNTIL RE-ENABLED. Example input:

```json
{"sources":["ted"],"countries":["ES","HR"],"daysBack":3,"maxResults":5,"maxChargeUsd":"0.035"}
```

This EU selection demonstrates the validated local adapter only; it is disabled for public Apify runs. Store-supported country: GB.

CPV prefixes of 2–7 digits and complete 8-digit CPV codes are accepted. Some OCDS releases only provide notice-level CPV, not a lot-specific code. CPV matching is therefore not proof that a particular lot requires those products or services.

**Minimum value filter:** Set both minAwardValue and currency (e.g. 50000, GBP). No currency conversion is attempted. Unreported awarded values remain null, and are omitted by default with requireAwardValue=true.

**Time windows:** FTS is indexed by *updated* timestamps, Contracts Finder by *published* timestamps, TED by publication date. These are **not** award-decision-date filters.

### Output and fidelity

Apify default dataset provides JSON, JSONL and CSV export. The Actor additionally stores **RESULTS.csv** and **SUMMARY** in its key-value store.

Required field names: source, award_id, ocid, winning_supplier_name, supplier_address, buyer_name, awarded_value, currency, contract_scope, award_date, notice_url, observed_at.

Extra provenance fields: lot_id, contract_id, winner_supplier_id, country_code, notice_publication_date, contract_signed_date, value_basis, value_scope, subcontract_opportunity_verified.

The final Boolean is always false. Supplier addresses may be null where not published. TED has no native OCDS OCID, so its ocid field is null.

**Never mislabel tender estimates:** OCDS tender.value, TED project estimates, overall notice totals, framework maximums and highest/lowest tenders are never used to supply missing winning contract amounts.

Find a Tender frequently reports amounts under matched contracts.value rather than awards.value, and may omit awards.date. In that case award_date stays null and the actual contract date is preserved separately in contract_signed_date. TED official AwardDate and IssueDate are likewise distinct.

Multi-lot and multi-winner: Every record is attached to its source award, lot and supplier IDs. TED explicitly joins LotResult → LotTender + SettledContract → TenderingParty → Organization. Winners in a consortium each have a row, but the price belongs to the **shared tender**, as identified by value_scope. Never sum repeated consortium amounts as if awarded separately. A value covering multiple UK lots is not blindly divided or copied to each lot.

### PPE pricing and cost cap

**Target Store price: USD 0.007 per unique award/lot**, equivalent to **USD 7.00 for 1,000 billed award/lot combinations** (without other price tiers). Multiple winning suppliers may create multiple dataset rows, while the shared award/lot triggers only one custom **unique-award-lot** event.

The Actor enforces both maxChargeUsd and the Apify per-run maximum charge. For accurate billing the Store configuration must set that custom event to USD 0.007 and make **apify-actor-start** and **apify-default-dataset-item** synthetic event prices zero/disabled. The event price is *not* activated merely by putting it in the source code. At Apify's published 20% commission, USD 7 gross revenue corresponds to USD 5.60 before compute/storage/proxy costs, which reduce net publisher profit further.

The time, page and maximum upstream request limits prevent unexpected resource consumption. Retries are bounded to three attempts for 429, 5xx and transport errors, respecting Retry-After with a bounded delay. Source pagination hostnames are validated; malformed or timed-out TED requests fail rather than pretending there were no records.

### Verifiable source mapping and live examples

See **SOURCE_MAPPING.md** for precise extraction paths including the off-platform EU adapter including the off-platform EU adapter, **tests/** for unit and live tests, and **evidence/** for executed test snapshots.

Source/legal attribution:

- UK Find a Tender (Open Government Licence): https://www.find-tender.service.gov.uk/Developer/Documentation
- UK Contracts Finder (official OCDS): https://www.contractsfinder.service.gov.uk/apidocumentation/Notices/1/GET-Published-Notice-OCDS-Search
- TED Search API v3: https://docs.ted.europa.eu/api/latest/search.html
- TED eForms award-results XML fields: https://docs.ted.europa.eu/eforms/latest/schema/competition-results.html
- TED legal notice: https://ted.europa.eu/en/legal-notice

This is an independent commercial analysis tool, not an official procurement agency. A public award announcement provides no automatic evidence of subcontracting demand; verify any independently pursued business opportunity directly with the supplier.

### Local development

```bash
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
PYTHONPATH=. .venv/bin/python -m unittest discover -s tests -v
PYTHONPATH=. .venv/bin/python tests/live_test.py
```

Do not place credentials or session cookies in these files. Deploy from the authorised Apify account only.

# Actor input Schema

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

Currently supported: UK Find a Tender and Contracts Finder. TED was verified on Netcup but is disabled on Apify cloud due to HTTP 202 empty XML.

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

Currently GB only (including UK); EU TED input disabled pending official XML access from Apify cloud.

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

Optional, e.g. 72, 72000000, 45000000. CPV is a filter, not proof of subcontract demand.

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

Find a Tender uses update timestamps; Contracts Finder uses publication timestamps; TED uses publication date. One to 90 days.

## `minAwardValue` (type: `string`):

Numeric threshold in the selected currency, not a converted or estimated budget. Requires currency when > 0.

## `currency` (type: `string`):

ISO 4217 code such as GBP or EUR. No exchange-rate conversion. Leave blank to accept all currencies.

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

Hard limit on individual supplier rows; one multi-supplier award/lot is charged only once.

## `maxChargeUsd` (type: `string`):

Upper limit for pay-per-event charges ($0.007 per unique award/lot), also bounded by Apify run charge limit.

## `requireAwardValue` (type: `boolean`):

Exclude records lacking per-award/contract/tender actual value; never backfill from tender estimates.

## `maxPagesPerSource` (type: `integer`):

Limits official API pagination per selected source/country.

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

All source calls and retries combined. Bounded to prevent runaway calls.

## `maxRunSeconds` (type: `integer`):

Stops controlled requests before the configured time budget.

## Actor input object example

```json
{
  "sources": [
    "find_a_tender",
    "contracts_finder"
  ],
  "countries": [
    "GB"
  ],
  "cpvCodes": [],
  "daysBack": 7,
  "minAwardValue": "0",
  "currency": "",
  "maxResults": 10,
  "maxChargeUsd": "0.07",
  "requireAwardValue": true,
  "maxPagesPerSource": 2,
  "maxRequests": 50,
  "maxRunSeconds": 240
}
```

# Actor output Schema

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

No description

## `csv` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("afkdigital/newapi19-contract-award-winner-leads").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("afkdigital/newapi19-contract-award-winner-leads").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 '{}' |
apify call afkdigital/newapi19-contract-award-winner-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,afkdigital/newapi19-contract-award-winner-leads"
        }
    }
}
```

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/uyjbDdf2adhVKznuy/builds/G0kC7J6NjjmUBS1S7/openapi.json
