UK Tenders Monitor - Contracts Finder & Find a Tender Alerts
Pricing
$4.00 / 1,000 tender notices
UK Tenders Monitor - Contracts Finder & Find a Tender Alerts
Monitor new UK public-sector tenders from the official Contracts Finder and Find a Tender APIs. Filter by keyword, CPV code, value, region and buyer, get only new notices on a schedule, and alert Slack or Discord for $0.004/notice.
Pricing
$4.00 / 1,000 tender notices
Rating
0.0
(0)
Developer
Luke Hunter
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
For bid writers, SME suppliers, consultancies and sales teams who sell to the UK public sector. Get new UK tenders from the two official government registers, Contracts Finder and Find a Tender, in one clean dataset. Filter by keyword, CPV code, contract value, region and buyer, return only notices you have not seen before on a schedule, and send each new one to Slack, Discord, Telegram or your phone.
$0.004 per delivered notice — 1,000 notices = $4
It reads the official open Contracts Finder API and Find a Tender API (OCDS data, published under the Open Government Licence). No scraping, no login, no proxy, no API key. Only notices that pass your filters are delivered, and only delivered notices are charged.
What you get
One row per notice, flattened and ready for a spreadsheet, CRM or alert: title, trimmed description, buyer and region, notice type and status, published date, bid deadline, value range in GBP, CPV codes with descriptions, procedure type, SME/VCSE suitability where the buyer states it, the public notice link, a link to tender documents, and the buyer's published contact email.
| You want | Set |
|---|---|
| IT tenders over £100k | cpvCodes: ["72"], minValue: 100000 |
| Anything mentioning a topic | keywords: ["cyber security", "penetration testing"] |
| One buyer family | buyerContains: "NHS" |
| One area | regions: ["London", "UKI"] |
| Who won what (competitor research) | noticeTypes: ["award"] |
| Early warning of future procurement | noticeTypes: ["planning"] |
| Only what is new since yesterday | onlyNewSinceLastRun: true on a daily Schedule |
Quick start
{"keywords": ["software"],"publishedWithinDays": 7,"maxItems": 20}
Run it with no filters at all and you get the 50 newest tender notices from the last 7 days across both registers.
Recipes
Daily IT tenders over £100k to Slack
{"cpvCodes": ["72"],"minValue": 100000,"noticeTypes": ["tender"],"onlyNewSinceLastRun": true,"maxItems": 50,"slackWebhookUrl": "https://hooks.slack.com/services/<T>/<B>/<token>"}
Save it as a Task, add a daily Schedule, and each morning Slack gets only the IT services tenders published since the last run. The first run is the baseline and sends what is open now.
NHS tenders to Discord
{"buyerContains": "NHS","noticeTypes": ["tender"],"publishedWithinDays": 14,"onlyNewSinceLastRun": true,"discordWebhookUrl": "https://discord.com/api/webhooks/<id>/<token>"}
SME-friendly construction work in the North West
{"cpvCodes": ["45"],"regions": ["North West", "Manchester", "Liverpool"],"maxValue": 500000,"publishedWithinDays": 30}
Then keep the rows where suitableForSme is true.
Last quarter's awards for one category (competitor and pricing research)
{"noticeTypes": ["award"],"cpvCodes": ["72"],"publishedFrom": "2026-07-13","publishedTo": "2026-10-10"}
Alerts: Discord, Telegram, Slack, Teams, Google Chat, phone push or any app
Add one or more destinations in the Notifications (optional) section and each run sends the notices it delivered. It is a monitor that notifies you: it only reads public registers, and never bids, applies, contacts a buyer or logs in anywhere.
| Channel | Fill in | What you get |
|---|---|---|
| Discord | discordWebhookUrl | One card per notice, 10 per message |
| Telegram | telegramBotToken + telegramChatId | Up to 10 notices per message, one line each |
| Slack | slackWebhookUrl | Block Kit message, up to 10 notices per message |
| Mattermost, Rocket.Chat | slackCompatibleWebhookUrl | A Markdown list |
| Microsoft Teams | teamsWebhookUrl | Adaptive Card from a Teams Workflows webhook |
| Google Chat | googleChatWebhookUrl | Card in a space |
| ntfy (phone push, no account) | ntfyTopic (optional ntfyServer, ntfyToken) | A push per notice, up to 10, then one "...and N more" |
| Pushover (phone push) | pushoverUserKey + pushoverAppToken | A push per notice, up to 10, then one "...and N more" |
| Zapier, Make, n8n, Pipedream | webhookUrl | One JSON POST per 100 delivered rows with the full dataset rows |
Each message reads like New tender: Provision of Cloud Hosting Services — Example NHS Trust, with the value range, closing date, published date, region, CPV codes, SME/VCSE flags and procedure, and a link to the notice. The description is never sent. Nothing is sent when a run delivers nothing, a failing channel never fails the run, and notifications are free: you pay only for delivered notices. Webhook URLs and tokens are stored as secret inputs.
Setup per channel is a minute or two: for Discord copy a channel webhook URL (Server Settings → Integrations → Webhooks); for Telegram create a bot with @BotFather and give its token plus a chat id; for Slack create an incoming webhook at api.slack.com/apps; for Teams use a Workflows "Post to a channel when a webhook request is received" URL.
maxNotifications (default 25, max 100) caps how many notices go to chat and phone channels per run; the rest are still in the dataset. Use onlyNewSinceLastRun for alerts, otherwise a scheduled run repeats the same notices.
Input
| Field | Default | What it does |
|---|---|---|
keywords | [] | Keep notices whose title or description contains any of these, case-insensitive. |
cpvCodes | [] | CPV prefix match. 72 = all IT services, 72200000-7 = software programming. Invalid codes stop the run with an error. |
minValue, maxValue | none | GBP bounds. A notice matches when its published value range overlaps them. Notices with no value, or in another currency, are left out while either bound is set. |
regions | [] | Match the buyer's region or locality, or a delivery region. Buyers publish names or NUTS codes (UKI), so try both. |
buyerContains | "" | Buyer name contains this text. |
noticeTypes | ["tender"] | tender (alias opportunity), award, planning (alias prior-information). |
sources | both | contracts-finder, find-a-tender. |
publishedWithinDays | 7 | 1 to 90 days back. |
publishedFrom, publishedTo | none | Explicit YYYY-MM-DD range, at most 90 days. Overrides publishedWithinDays. |
maxItems | 50 | Hard cap on delivered notices, 1 to 1000, newest first. |
onlyNewSinceLastRun | false | Deliver and charge only notices not delivered before for this same set of filters. |
stateStoreName | uk-tenders-monitor-seen-notices | Named store holding the alert memory. |
| notification fields | none | discordWebhookUrl, telegramBotToken, telegramChatId, slackWebhookUrl, slackCompatibleWebhookUrl, teamsWebhookUrl, googleChatWebhookUrl, ntfyTopic, ntfyServer, ntfyToken, pushoverUserKey, pushoverAppToken, webhookUrl, maxNotifications. |
Both registers are read and deduplicated: a notice published on both counts once (matched by notice id, or by OCID at the same stage), and the most recently published copy is kept. A tender and its later award are different notices and are kept separately.
How "only new" works
With onlyNewSinceLastRun, the Actor remembers each delivered notice by its OCID plus stage, in a named key-value store, per set of filters (changing a keyword starts a fresh baseline; changing maxItems or publishedWithinDays does not). An amended tender does not alert twice, but its award notice does. Only notices actually delivered are remembered, so anything held back by maxItems or your spending limit turns up on the next run.
Example output
{"source": "contracts-finder","noticeId": "11111111-aaaa-4bbb-8ccc-000000000001","ocid": "ocds-b5fd17-11111111-aaaa-4bbb-8ccc-000000000001","title": "Provision of Cloud Hosting Services","description": "The Trust requires cloud hosting & managed backup for clinical systems. Contract term 3 years.","buyerName": "Example NHS Trust","buyerRegion": "Yorkshire and The Humber","deliveryRegions": ["UKE", "Leeds"],"noticeType": "tender","status": "active","publishedDate": "2026-10-08T09:30:00Z","deadlineDate": "2026-11-05T12:00:00Z","valueLow": 100000,"valueHigh": 250000,"currency": "GBP","cpvCodes": ["72000000", "72500000"],"cpvDescriptions": ["IT services: consulting, software development, Internet and support", "Computer-related services"],"procedureType": "Open procedure","suitableForSme": true,"suitableForVcse": false,"url": "https://www.contractsfinder.service.gov.uk/Notice/11111111-aaaa-4bbb-8ccc-000000000001","documentsUrl": "https://example-trust.nhs.example/tenders/cloud-hosting.zip","contactEmail": "procurement.team@example-trust.nhs.example","scrapedAt": "2026-10-10T12:00:00.000Z"}
This sample is illustrative (synthetic buyer and domain names), shaped like the registers' OCDS data. Anything a notice does not publish is null, never guessed: when the buyer gives a single value it fills both valueLow and valueHigh; deadlineDate is the end of the tender period (for Find a Tender notices with several lots, the latest lot deadline); contactEmail is the organisational contact exactly as the buyer published it on the notice.
Use with AI agents (MCP)
This Actor works as a tool for Claude, ChatGPT, Cursor and other MCP clients through Apify's MCP server. Every input is optional, so a call can be as small as keywords and publishedWithinDays.
Claude Desktop (claude_desktop_config.json), with your own token from Apify Console > Settings > API & Integrations:
{"mcpServers": {"apify-uk-tenders": {"command": "npx","args": ["-y", "mcp-remote","https://mcp.apify.com?tools=lukehunter/uk-tenders-monitor","--header", "Authorization: Bearer ${APIFY_TOKEN}"],"env": { "APIFY_TOKEN": "<YOUR_APIFY_TOKEN>" }}}}
Clients that support OAuth (Claude.ai, VS Code) can connect with just the URL https://mcp.apify.com?tools=lukehunter/uk-tenders-monitor and sign in to Apify. Never paste a real token into a shared file or chat.
Example. You ask: "Which UK councils have published cyber security tenders worth over £50k this fortnight, and when do they close?" The agent calls the tool lukehunter--uk-tenders-monitor with:
{"keywords": ["cyber security"],"buyerContains": "council","minValue": 50000,"publishedWithinDays": 14,"maxItems": 25}
It is charged $0.004 per delivered notice, capped by maxItems. Each input property description is short and carries an example, so agents fill it in correctly.
Pricing
Pay-per-event: $0.004 per delivered notice. A notice is charged only after it is accepted into the dataset, and only if it passed your filters (and, in alert mode, was not delivered before).
| Notices delivered | Cost |
|---|---|
| 20 | $0.08 |
| 50 (default cap) | $0.20 |
| 1,000 (maximum) | $4.00 |
maxItems (hard maximum 1,000) and your Apify per-run spending limit both stop delivery before the cap is passed. Reading the registers, filtering and sending notifications cost nothing extra. Price changes follow Apify's notice rules; the Pricing tab always shows the rate you are charged.
Limitations
- Official open data, Open Government Licence. The notices are Crown copyright / public sector information from the Contracts Finder and Find a Tender open APIs, re-published under the Open Government Licence v3.0. If you republish the data, attribute the source: "Contains public sector information licensed under the Open Government Licence v3.0."
- Not affiliated with the UK Government. This is an independent Actor reading public APIs. Always confirm deadlines and requirements on the official notice page (the
urlfield) before bidding. - Coverage is what the registers publish. Contracts Finder and Find a Tender cover different thresholds and nations; some devolved-nation and below-threshold opportunities are on other portals. The Actor does not read those.
- Values are often missing. Many notices publish no value. With
minValueormaxValueset they are left out (they cannot be compared); leave the bounds empty to see them withnullvalues. - Regions are as published. Buyers write a name, a locality or a NUTS code, so a region filter matches text, not geography.
- Time window, not archive. Each run covers at most 90 days. Large windows read many pages from the APIs, politely and one at a time, so they take longer; a run stops at 200 pages per source or 15 minutes and says so in its status message.
- Find a Tender uses its update time. For that register the window is applied to when a notice was last updated, so an amended older notice can appear; the
publishedDatefield shows the date used. - Contact emails are what buyers published. They are organisational procurement contacts printed on the notice. Use them in line with UK GDPR and PECR; for marketing to individuals you need a lawful basis.
- Rate limits. Requests are paced, and 429/5xx responses are retried with backoff. If a register stays unavailable the run reports it per source and continues with the other; if both fail, nothing is charged and the run fails with a clear message.
Use it from your code, Make, Zapier or n8n
Built for automated pipelines: small runs, stable field names, one row per item, and you pay only for rows actually delivered.
One API call that runs the Actor and returns the data (replace $APIFY_TOKEN with your token from Apify Console → Settings → Integrations):
curl -s -X POST "https://api.apify.com/v2/acts/lukehunter~uk-tenders-monitor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"keywords": ["software"], "publishedWithinDays": 7, "maxItems": 20}'
JavaScript (npm i apify-client):
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('lukehunter~uk-tenders-monitor').call({"keywords": ["software"],"publishedWithinDays": 7,"maxItems": 20});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Python (pip install apify-client):
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('lukehunter~uk-tenders-monitor').call(run_input={"keywords": ["software"], "publishedWithinDays": 7, "maxItems": 20})items = client.dataset(run['defaultDatasetId']).list_items().items
Schedules, webhooks and no-code tools: save your input as a Task, add a Schedule (e.g. hourly or daily), and attach a webhook or one of the Integrations tab's connectors (Make, Zapier, n8n, Google Sheets, Slack) to push each run's results into your own system.
Only new items each run: set "onlyNewSinceLastRun": true on a scheduled Task and every run after the first delivers, and charges for, only items it hasn't delivered before for that same input. That makes it a ready-made change feed.
Feedback: an honest rating on the Store page, good or bad, helps others decide if this Actor fits their needs. Missing a field or found a problem? Open an issue on the Actor page.
FAQ
Is this the official Contracts Finder API and Find a Tender API? Yes. It reads the public OCDS endpoints the Cabinet Office publishes, with an honest User-Agent, no login and no proxy.
What is a CPV code? The Common Procurement Vocabulary is the EU/UK classification of what is being bought. 72 is IT services, 45 construction, 33 medical equipment, 79 business services. Enter any 2 to 8 digits as a prefix.
Why is a notice I saw on the website missing? Check its type (the default is tender only), its publication date against your window, and whether minValue/maxValue excluded it for having no value.
Will an amended tender alert me again? No. Alerts are keyed on the procurement (OCID) and stage. Its award notice is a new alert.
Can I get tenders in Slack, Discord or Telegram every morning? Yes: set onlyNewSinceLastRun, add a destination and a daily Schedule. See the recipes above.
Does it submit bids or contact buyers? No. It only reads and reports.
Related Actors
Other data tools from the same developer, built to the same standard: official or public sources, hard cost caps, and honest documentation of limits.
- Federal Register Rule Effective-Date Radar: final federal rules about to take effect, with citations, dockets and urgency.
- Chicago Contract Recompete & Extension Radar: expiring City of Chicago contracts with extension history, for recompete prospecting.
- Bank Branch Closings & Merger Radar (FDIC): new US bank branch closings, openings and mergers from the FDIC.
- Chicago New Business License Radar: newly licensed Chicago businesses as opening leads, grouped by category.
- NYC FDNY Contractor Leads & Hearing Radar: fresh NYC fire-code summonses routed by remediation trade, with hearing dates.
- RCRA Enforcement Response Leads: new EPA hazardous-waste (RCRA) enforcement actions and penalties, by state.
- Emerging Federal Contractor Radar: companies that just won their first federal contracts, from USAspending.gov.
- Hospital Price Transparency Enforcement Leads: hospitals with recent CMS price transparency warning notices, CAP requests and CMP notices.