The UK publishes public-sector tenders on two official sites: Find a Tender (UK-wide, mostly higher-value contracts) and Contracts Finder (England, lower-value contracts). Both have open-data APIs, but they use different endpoints, different date filters and a strict rate limit. If all you want is "new software tenders over £50k, every morning", that is a lot of plumbing.

This guide uses the UK Tenders Actor on Apify, which reads both official APIs and returns one flat record per notice.

1. Pick your filters

Tenders are classified with CPV codes. A few common divisions:

CPV Sector
72000000 IT services
48000000 Software packages
45000000 Construction work
79000000 Business services
85000000 Health and social work

A division code matches everything under it, so 72000000 covers all IT services.

2. Run it once

curl -X POST "https://api.apify.com/v2/acts/studded_lantana~uk-tenders/run-sync-get-dataset-items" \ -H "Authorization: Bearer $APIFY_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "stages": ["tender"], "daysBack": 2, "cpvCodes": ["72000000", "48000000"], "minValue": 50000, "openOnly": true, "maxItems": 100 }' 

You get back a JSON array. Each item has title, buyer_name, value_amount, tender_deadline, cpv_descriptions and a url to the official notice.

daysBack counts calendar days in UTC including today, so 2 means yesterday and today. With 1 a morning run would only see what was published since midnight.

Setting minValue drops notices where the buyer published no value. If you would rather see everything, leave it out.

3. Turn it into a morning digest

import os from apify_client import ApifyClient client = ApifyClient(os.environ["APIFY_TOKEN"]) run = client.actor("studded_lantana/uk-tenders").call(run_input={ "stages": ["tender"], "daysBack": 2, "cpvCodes": ["72000000", "48000000"], "openOnly": True, }) for n in client.dataset(run.default_dataset_id).iterate_items(): value = f"£{n['value_amount']:,.0f}" if n.get("value_amount") else "value not published" deadline = (n.get("tender_deadline") or "no deadline given")[:10] print(f"{n['title']}\n {n['buyer_name']} | {value} | closes {deadline}\n {n['url']}\n") 

Send that text wherever you read things: email, Slack or a Google Sheet. A narrow filter can return nothing on a quiet day: when I ran this on a Saturday in October 2026, the two days held 24 notices and none was an open IT tender. Over the seven days before, the same filter returned several.

4. Schedule it

In the Apify console, open the Actor, save your input as a task, and add a schedule (for example 0 7 * * 1-5 for weekdays at 07:00). Because each run covers two days, every notice shows up on two consecutive runs, and Find a Tender filters by the date a notice was last updated, so an amended notice can come back later. Keep the source and notice_id of what you have already sent and skip those.

5. See who is winning

Change "stages" to ["award"] and each record gains award_value_total, award_date and a suppliers list. That tells you which companies win work from the buyers you care about.

Cost

$0.005 per run plus $0.002 per notice returned. A run that returns 20 notices costs 4.5 cents.

The data is public sector information licensed under the Open Government Licence v3.0. The Actor is not affiliated with the Cabinet Office, Find a Tender or Contracts Finder.