EU & UK Tender Match Monitor avatar

EU & UK Tender Match Monitor

Pricing

from $5.00 / 1,000 tender matches

Go to Apify Store
EU & UK Tender Match Monitor

EU & UK Tender Match Monitor

Find, rank, normalize, and monitor official EU TED and UK Find a Tender notices.

Pricing

from $5.00 / 1,000 tender matches

Rating

0.0

(0)

Developer

FetchFinch

FetchFinch

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Find procurement opportunities that fit a supplier, not just notices that contain a word.

Unofficial Actor: This product is not affiliated with, sponsored by, or endorsed by the European Union, TED, the UK Cabinet Office, or Find a Tender.

This Apify Actor reads the official EU Tenders Electronic Daily (TED) and UK Find a Tender APIs, converts both formats into one stable schema, assigns an explainable fit score, and can emit only new or materially changed matches on recurring runs. It does not scrape result pages, require source credentials, or call an LLM.

What it gives you

  • One normalized dataset for EU/EEA and UK notices
  • Profile, keyword, exclusion, CPV, country, stage, date, and deadline filters
  • Deterministic fitScore from 0 to 100 with human-readable matchReasons
  • Stable procurement IDs and cross-run change detection
  • Direct official notice, PDF, XML, and tender-document links when published
  • A RUN_SUMMARY record with source counts, generated TED query, filtering counts, partial-source errors, and monitor statistics
  • JSON, JSONL, CSV, Excel, XML, RSS, and API delivery through Apify datasets

Quick start

Use a concrete company description and add the phrases buyers are likely to publish:

{
"companyProfile": "We build secure cloud data platforms, analytics dashboards, API integrations, and data migration solutions for public-sector organizations.",
"keywords": ["data platform", "analytics dashboard", "API integration"],
"cpvCodes": ["72000000"],
"countries": ["DEU", "FRA", "IRL", "GBR"],
"sources": ["TED", "UK_FTS"],
"stages": ["competition"],
"lookbackDays": 14,
"minFitScore": 25,
"maxItems": 100,
"scanLimit": 500,
"mode": "search"
}

See examples/search.json and examples/monitor.json for complete starting points.

Search and monitor modes

search ranks current matches and writes them with changeType: "search_result".

monitor stores a compact snapshot in a named Apify key-value store. Later runs with the same monitorId emit new and changed matches; unchanged records remain quiet unless emitUnchanged is enabled. Use baselineBehavior: "store_only" to make the first run silent, or "emit" to receive the current backlog.

For a recurring monitor:

  1. Create an Apify Task with mode: "monitor" and a unique monitorId.
  2. Leave publishedFrom and publishedTo unset so lookbackDays moves with every run.
  3. Run the Task once to establish the baseline.
  4. Add an Apify schedule and a webhook, email, Slack, Make, or Zapier integration.

The Actor retains inactive state for 400 days and caps each monitor at 25,000 tracked procurements. Ranking-only fields do not trigger false change events. Material changes such as deadline, value, title, stage, buyer, CPV, documents, or notice publication do.

How matching works

The Actor combines priority keywords with useful terms derived from companyProfile. Explicit keywords receive priority weight. Terms inferred from the profile receive a lower supporting weight, and generic standalone words inferred from prose are ignored. Words and phrases match only at complete word boundaries, so api does not match a place name such as Krapina, and build does not match building. Each normalized notice is scored deterministically:

  • Priority/profile title match: 18/12 points per term, up to 54
  • Priority/profile description match: 8/4 points per term, up to 24
  • Priority/profile buyer-name match: 4/2 points per term, up to 8
  • Broad matching CPV family (2-3 meaningful prefix digits): 20 points
  • Specific matching CPV family (4+ meaningful prefix digits): 32 points

CPV filters are hierarchical: 72000000 matches child codes in the IT family, while a more specific code such as 7226 is selective. At the default minFitScore of 25, a broad CPV match needs supporting text; set the threshold to 15 to include CPV-only leads. Any complete-word excludeKeywords match drops the record. This model is intentionally transparent and reproducible; raise minFitScore toward 40 for a more selective result set.

Output

Every dataset item follows the same contract regardless of source:

{
"source": "TED",
"canonicalId": "TED:cca0901b-c163-4e7f-be96-fb495ad37197",
"sourceNoticeId": "529733-2026",
"title": "Data platform and migration services",
"buyerName": "Example Contracting Authority",
"countries": ["DEU"],
"cpvCodes": ["72000000", "72260000"],
"noticeStage": "competition",
"publicationDate": "2026-07-31+02:00",
"deadline": "2026-08-25T23:59:59+02:00",
"estimatedValue": 1250000,
"currency": "EUR",
"fitScore": 38,
"matchReasons": ["Title matches: data platform", "CPV matches (broad family, 20 points): 72000000"],
"matchedKeywords": ["data platform"],
"matchedCpvCodes": ["72000000"],
"changeType": "new",
"changedFields": [],
"url": "https://ted.europa.eu/en/notice/-/detail/529733-2026"
}

Missing source values are returned as null, an empty string, or an empty array as appropriate. estimatedValue is not currency-converted. TED procedure values are preferred; otherwise the first published lot value may be used and identified by valueBasis.

Important input behavior

  • The date window is inclusive. TED applies it to publication date. Find a Tender's public OCDS endpoint exposes an update window, so UK results represent notices created or updated during the same period.
  • scanLimit applies separately to each selected source and must be at least maxItems. It bounds API work before local scoring.
  • UK Find a Tender is skipped when countries is non-empty and excludes GBR.
  • expertQuery is ANDed with generated TED filters and does not affect UK results.
  • If one source fails, results from the other source are still delivered and the run summary reports succeeded_with_source_errors. The run fails if every attempted source fails.

Run locally

Python 3.11 or newer is required.

python3 -m venv .venv
.venv/bin/pip install -r requirements-dev.txt
mkdir -p storage/key_value_stores/default
cp examples/search.json storage/key_value_stores/default/INPUT.json
APIFY_LOCAL_STORAGE_DIR=./storage .venv/bin/python -m src

Quality checks:

.venv/bin/ruff check src tests
.venv/bin/pytest -q

Local output is written under storage/datasets/default, with the summary at storage/key_value_stores/default/RUN_SUMMARY.json.

Deploy to Apify

Install the Apify CLI, then run:

apify login
apify push

The repository includes the Dockerfile, Actor definition, input UI, dataset view, and output links needed for a cloud build. The Actor is HTTP-only and capped at 512 MB; no Apify Proxy or browser is required.

After publishing, the Actor can be called with Apify's normal run endpoints and the default dataset endpoint. Use the API tab in Apify Console to copy account-specific URLs and code snippets without exposing a token in source control.

Sources and reuse

Source names and official links are retained for attribution. Procurement data can contain third-party material; users remain responsible for their downstream use.

Scope

This version finds and monitors public notice metadata. It does not log in to buyer portals, download gated attachments, prepare bids, assess legal eligibility, or replace review of the official notice. A fit score is a discovery aid, not a bid/no-bid decision.